/* Parser for JAL.
Copyright (C) 2010 Albert Faber

Parser actions based on the gcc c parser; structure somewhat

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */


/* TODO:
Finish following items:
Bit identifiers
Procedure/function delcaration
Psuedo funcs
Arrays

*/

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
#include "rtl.h"
#include "langhooks.h"
#include "input.h"
#include "cpplib.h"
#include "timevar.h"
#include "c-pragma.h"
#include "jal-tree.h"
#include "flags.h"
#include "output.h"
#include "toplev.h"
#include "ggc.h"
#include "c-common.h"
#include "vec.h"
#include "target.h"
#include "cgraph.h"
#include "jal.h"
#include "jal-lex.h"
#include "jal-cpp.h"
#include "jal-opts.h"

static bool g_isInCast = false;

//static int jal_parser_trace_level = 0;

static int jal_parser_do_trace(const char *format, ...);

static int jal_parser_do_trace(const char *format, ...)
{  
	va_list arguments;
	va_start(arguments, format);
	if ( option_parser_trace!=0 )
	{
		vfprintf(stderr, format, arguments);
	}
	va_end(arguments);
	return(0);
}

#define jal_parser_trace(format, ...) { jal_parser_do_trace( "%s(%d): ", __FUNCTION__, (int)(__LINE__) ); jal_parser_do_trace( format, ## __VA_ARGS__); jal_parser_do_trace("\n" ); }
#define jal_parser_trace0(a) { jal_parser_do_trace( "%s(%d): ", __FUNCTION__, (int)(__LINE__) ); jal_parser_do_trace( "%s", a); jal_parser_do_trace("\n" ); }

void jal_parse_init (void);


/* The reserved keyword table.  */
struct resword
{
	const char *word;
	ENUM_BITFIELD(rid) rid : 16;
	unsigned int disable   : 16;
};

/* Disable mask.  Keywords are disabled if (reswords[i].disable &
mask) is _true_.  */
#define D_C89	0x01	/* not in C89 */
//#define D_EXT	0x02	/* GCC extension */
//#define D_EXT89	0x04	/* GCC extension incorporated in C99 */
//#define D_OBJC	0x08	/* Objective C only */


static const struct resword reswords[] =
{
	{ "_Decimal32",       RID_DFLOAT32,  D_EXT },
	{ "_Decimal64",       RID_DFLOAT64,  D_EXT },
	{ "_Decimal128",      RID_DFLOAT128, D_EXT },
	{ "_Fract",           RID_FRACT,     D_EXT },
	{ "_Accum",           RID_ACCUM,     D_EXT },
	{ "_Sat",             RID_SAT,       D_EXT },
	{ "__alignof",	RID_ALIGNOF,	0 },
	{ "__alignof__",	RID_ALIGNOF,	0 },
	{ "__asm",		RID_ASM,	0 },
	{ "__asm__",		RID_ASM,	0 },
	{ "__attribute",	RID_ATTRIBUTE,	0 },
	{ "__attribute__",	RID_ATTRIBUTE,	0 },
	{ "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 },
	{ "__builtin_offsetof", RID_OFFSETOF, 0 },
	{ "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 },
	{ "__builtin_va_arg",	RID_VA_ARG,	0 },
	{ "__const",		RID_CONST,	0 },
	{ "__const__",	RID_CONST,	0 },
	{ "__extension__",	RID_EXTENSION,	0 },
	{ "__func__",		RID_C99_FUNCTION_NAME, 0 },
	{ "__inline",		RID_INLINE,	0 },
	{ "__inline__",	RID_INLINE,	0 },
	{ "__label__",	RID_LABEL,	0 },
	{ "__restrict",	RID_RESTRICT,	0 },
	{ "__restrict__",	RID_RESTRICT,	0 },
	{ "__signed",		RID_SIGNED,	0 },
	{ "__signed__",	RID_SIGNED,	0 },
	{ "__thread",		RID_THREAD,	0 },
	{ "__typeof",		RID_TYPEOF,	0 },
	{ "__typeof__",	RID_TYPEOF,	0 },
	{ "__volatile",	RID_VOLATILE,	0 },
	{ "__volatile__",	RID_VOLATILE,	0 },
	{ "asm",		RID_ASM,	D_EXT },
	{ "auto",		RID_AUTO,	0 },
	{ "case",		RID_CASE,	0 },
	{ "char",		RID_CHAR,	0 },
	{ "const",		RID_CONST,	0 },
	{ "continue_NO",		RID_CONTINUE,	0 },
	{ "do",			RID_DO,		0 },
	{ "double",		RID_DOUBLE,	0 },
	{ "else",		RID_ELSE,	0 },
	{ "enum",		RID_ENUM,	0 },
	{ "extern",		RID_EXTERN,	0 },
	{ "float",		RID_FLOAT,	0 },
	{ "for",		RID_FOR,	0 },
	{ "for",		RID_FOR,	0 },
	{ "goto",		RID_GOTO,	0 },
	{ "if",			RID_IF,		0 },
	{ "inline_JAL",		RID_INLINE,	0 },
	{ "int",		RID_INT,	0 },
	{ "long",		RID_LONG,	0 },
	{ "register",	RID_REGISTER,	0 },
	{ "return",		RID_RETURN,	0 },
	{ "short",		RID_SHORT,	0 },
	{ "signed",		RID_SIGNED,	0 },
	{ "sizeof",		RID_SIZEOF,	0 },
	{ "static",		RID_STATIC,	0 },
	{ "struct",		RID_STRUCT,	0 },
	{ "typedef",	RID_TYPEDEF,	0 },
	{ "typeof",		RID_TYPEOF,	D_EXT },
	{ "union",		RID_UNION,	0 },
	{ "unsigned",	RID_UNSIGNED,	0 },
	{ "void",		RID_VOID,	0 },
	{ "volatile",	RID_VOLATILE,	0 },
	{ "while",		RID_WHILE,	0 },
	{ "end",		RID_END,		0 },
	{ "var",		RID_VAR,	0},
	{ "forever",	RID_FOREVER,	0 },
	{ "loop",		RID_LOOP,		0 },
	{ "begin",		RID_BEGIN,	0 },
	{ "exit",		RID_EXIT,	0 },
	{ "repeat",		RID_REPEAT, 0},
	{ "until",		RID_UNTIL, 0 },
	{ "block",		RID_BLOCK,0},
	{ "elsif",		RID_ELSIF,0},
	{ "then",		RID_THEN, 0 },
	{ "at",			RID_AT, 0},

	{ "byte",		RID_BYTE, 0 },
	{ "sbyte",		RID_SBYTE, 0 },
	{ "word",		RID_WORD, 0 },
	{ "sword",		RID_SWORD, 0 },
	{ "dword",		RID_DWORD, 0 },
	{ "sdword",		RID_SDWORD, 0 },
	{ "procedure",	RID_PROCEDURE, 0 },
	{ "function",	RID_FUNCTION, 0 },
	{ "is",			RID_IS, 0 },
	{ "in",			RID_IN, 0 },
	{ "out",		RID_OUT, 0 },
	{ "using",		RID_USING, 0 },
	{ "otherwise",		RID_OTHERWISE, 0 },
	{ "of",			RID_OF, 0 },
	{ "alias",		RID_ALIAS, 0 },
	{ "pragma",		RID_PRAGMA, 0 },
};
#define N_reswords (sizeof reswords / sizeof (struct resword))

/* Initialization routine for this file.  */


// #define GGC_CNEWVEC(T, N)	((T *) ggc_alloc_cleared ((N) * sizeof(T)))
// #define GGC_RESIZEVEC(T, P, N)  ((T *) ggc_realloc ((P), (N) * sizeof (T)))


#define PARSER_TRACE_ENTER() { jal_parser_do_trace( "ENTER %s(%d)\n", __FUNCTION__,__LINE__); };
#define PARSER_TRACE_EXIT() { jal_parser_do_trace( "EXIT %s(%d)\n", __FUNCTION__,__LINE__); };


typedef struct JAL_ALIAS_TYPE
{
	tree alias_name;
	tree alias_value;
} JAL_ALIAS;

static JAL_ALIAS* jal_aliases_ptr = NULL;
static int jal_aliases_len = -1;
static int jal_aliases_alloc = -1;

static void jal_alias_realloc(void);

static void jal_alias_realloc(void)
{
	if ( jal_aliases_ptr == NULL )
	{
		jal_aliases_len = 0;
		jal_aliases_alloc = 1000;
		jal_aliases_ptr = GGC_CNEWVEC(JAL_ALIAS, jal_aliases_alloc);
	}
	else
	{
		jal_aliases_alloc *= 2;
		jal_aliases_ptr = GGC_RESIZEVEC(JAL_ALIAS, jal_aliases_ptr, jal_aliases_alloc);
	}
}



void jal_parse_init( void )
{
	/* The only initialization required is of the reserved word
	identifiers.  */
	unsigned int i;
	tree id;
	int mask = (flag_isoc99 ? 0 : D_C89)
		| (flag_no_asm ? (flag_isoc99 ? D_EXT : D_EXT|D_EXT89) : 0);

	jal_alias_realloc();

	if (!c_dialect_objc ())
		mask |= D_OBJC;

	ridpointers = GGC_CNEWVEC (tree, (int) RID_MAX);
	for (i = 0; i < N_reswords; i++)
	{
		/* If a keyword is disabled, do not enter it into the table
		and so create a canonical spelling that isn't a keyword.  */
		if (reswords[i].disable & mask)
			continue;

		id = get_identifier (reswords[i].word);
		C_SET_RID_CODE (id, reswords[i].rid );
		JAL_IS_RESERVED_WORD (id) = 1;
		ridpointers [(int) reswords[i].rid] = id;
	}


}

// AF TODO REMOVE WHEN gotting rid of c-decl
void c_parse_init( void )
{
	jal_parse_init();
}

/* The JAL lexer intermediates between the lexer in jal cpp and jal-lex.c
and the Jal parser.  Unlike the C++ lexer, the parser structure
stores the lexer information instead of using a separate structure.
Identifiers are separated into ordinary identifiers, type names,
keywords and some other Objective-C types of identifiers, and some
look-ahead is maintained.

??? It might be a good idea to lex the whole file up front (as for
C++).  It would then be possible to share more of the C and C++
lexer code, if desired.  */

/* The following local token type is used.  */

/* A keyword.  */
#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))

/* More information about the type of a CPP_NAME token.  */
typedef enum c_id_kind {
	/* An ordinary identifier.  */
	C_ID_ID,
	/* An identifier declared as a typedef name.  */
	C_ID_TYPENAME,
	/* An identifier declared as an Objective-C class name.  */
	C_ID_CLASSNAME,
	/* Not an identifier.  */
	C_ID_NONE
} c_id_kind;

/* A single C token after string literal concatenation and conversion
of preprocessing tokens to tokens.  */
typedef struct jal_token GTY (())
{
	/* The kind of token.  */
	ENUM_BITFIELD (cpp_ttype) type : 8;
	/* If this token is a CPP_NAME, this value indicates whether also
	declared as some kind of type.  Otherwise, it is C_ID_NONE.  */
	ENUM_BITFIELD (c_id_kind) id_kind : 8;
	/* If this token is a keyword, this value indicates which keyword.
	Otherwise, this value is RID_MAX.  */
	ENUM_BITFIELD (rid) keyword : 8;
	/* If this token is a CPP_PRAGMA, this indicates the pragma that
	was seen.  Otherwise it is PRAGMA_NONE.  */
	ENUM_BITFIELD (pragma_kind) pragma_kind : 8;
	/* True if this token is from a system header.  */

	tree value;
	/* The location at which this token was found.  */
	location_t location;
} jal_token;

/* A parser structure recording information about the state and
context of parsing.  Includes lexer information with up to two
tokens of look-ahead; more are not needed for C.  */
typedef struct jal_parser GTY(())
{
	/* The look-ahead tokens.  */
	jal_token tokens[2];
	/* How many look-ahead tokens are available (0, 1 or 2).  */
	short tokens_avail;
	/* True if a syntax error is being recovered from; false otherwise.
	jal_parser_error sets this flag.  It should clear this flag when
	enough tokens have been consumed to recover from the error.  */
	BOOL_BITFIELD error : 1;
	/* True if we're processing a pragma, and shouldn't automatically
	consume CPP_PRAGMA_EOL.  */
	BOOL_BITFIELD in_pragma : 1;
	/* True if we're parsing the outermost block of an if statement.  */
	BOOL_BITFIELD in_if_block : 1;
	/* True if we want to lex an untranslated string.  */
	BOOL_BITFIELD lex_untranslated_string : 1;
	/* Objective-C specific parser/lexer information.  */
	BOOL_BITFIELD objc_pq_context : 1;
	/* The following flag is needed to contextualize Objective-C lexical
	analysis.  In some cases (e.g., 'int NSObject;'), it is
	undesirable to bind an identifier to an Objective-C class, even
	if a class with that name exists.  */
	BOOL_BITFIELD objc_need_raw_identifier : 1;
} jal_parser;


/* The actual parser and external interface.  ??? Does this need to be
garbage-collected?  */

static GTY (()) jal_parser *the_parser;


static void jal_parser_resolve_alias( jal_parser *parser, 	jal_token *token );
static void jal_parser_resolve_alias( jal_parser *parser, 	jal_token *token )
{
	int i = 0;

	PARSER_TRACE_ENTER();

	parser=parser;

	if ( token->type == CPP_NAME )
	{
		for ( i = 0; i< jal_aliases_len; i++ )
		{
			const char* p1 = IDENTIFIER_POINTER (token->value);
			const char* p2 = IDENTIFIER_POINTER (jal_aliases_ptr[ i ].alias_name);
			const char* p3 = IDENTIFIER_POINTER (jal_aliases_ptr[ i ].alias_value);
	
			jal_parser_trace( "ALIAS CHECK :%s: with :%s: \n", p1, p2 );

			if  ( memcmp( p1, p2, strlen( p2 ) ) == 0 )
			{
				jal_parser_trace( "ALIAS CHECK OK, replace :%s: with :%s: \n", p2, p3 );
				token->value = get_identifier( p3 );
			}
		}
	}
	PARSER_TRACE_EXIT();
}



/* Consume the next token from PARSER.  */
static void
jal_print_token (FILE * stream, jal_token *token);

/* Read in and lex a single token, storing it in *TOKEN.  */

static void jal_lex_one_token (jal_parser *parser, jal_token *token)
{
	timevar_push (TV_LEX);

	PARSER_TRACE_ENTER();

	//token->type = jal_lex_with_flags (&token->value, &token->location, NULL,
	//	(parser->lex_untranslated_string
	//	? C_LEX_STRING_NO_TRANSLATE : 0));

	token->type = jal_lex_next_token_loc (&token->value, &token->location, NULL,
		(parser->lex_untranslated_string
		? C_LEX_STRING_NO_TRANSLATE : 0));

	token->id_kind = C_ID_NONE;
	token->keyword = RID_MAX;
	token->pragma_kind = PRAGMA_NONE;
	//token->in_system_header = in_system_header;
	jal_parser_resolve_alias( parser, token );

	switch (token->type)
	{
	case CPP_NAME:
		{
			tree decl;

			if (JAL_IS_RESERVED_WORD (token->value))
			{
				enum rid rid_code = C_RID_CODE (token->value);

				/* Return the canonical spelling for this keyword.  */
				token->value = ridpointers[(int) rid_code];
				token->type = CPP_KEYWORD;
				token->keyword = rid_code;
				break;
			}

			decl = lookup_name (token->value);
			if (decl)
			{
				if (TREE_CODE (decl) == TYPE_DECL)
				{
					token->id_kind = C_ID_TYPENAME;
					break;
				}
			}
			token->id_kind = C_ID_ID;
		}
		break;
	case CPP_AT_NAME:
		/* This only happens in Objective-C; it must be a keyword.  */
		token->type = CPP_KEYWORD;
		token->keyword = C_RID_CODE (token->value);
		break;
	case CPP_COLON:
	case CPP_COMMA:
	case CPP_CLOSE_PAREN:
	case CPP_SEMICOLON:
		break;
	case CPP_PRAGMA:
		/* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
		token->pragma_kind = TREE_INT_CST_LOW (token->value);
		token->value = NULL;
		break;
	default:
		break;
	}
	timevar_pop (TV_LEX);
	PARSER_TRACE_EXIT();
}




static void
jal_print_token (FILE * stream, jal_token *token)
{
  /* We don't use cpp_type2name here because the parser defines
     a few tokens of its own.  */
  static const char *const token_names[] = {
    /* cpplib-defined token types */
#define OP(e, s) #e,
#define TK(e, s) #e,
    TTYPE_TABLE
#undef OP
#undef TK
    /* C++ parser token types - see "Manifest constants", above.  */
    "KEYWORD",
    "KEYWORD",
    "NESTED_NAME_SPECIFIER",
    "PURGED"
  };

  stream = stream;

  /* If we have a name for the token, print it out.  Otherwise, we
     simply give the numeric code.  */
  gcc_assert (token->type < ARRAY_SIZE(token_names));
  jal_parser_do_trace ("%s", token_names[token->type] );

 // /* For some tokens, print the associated data.  */
 switch (token->type)
 {
	case CPP_KEYWORD:
 //     /* Some keywords have a value that is not an IDENTIFIER_NODE.
	// For example, `struct' is mapped to an INTEGER_CST.  */
		if (TREE_CODE (token->value) != IDENTIFIER_NODE)
			jal_parser_do_trace (":%s:", IDENTIFIER_POINTER (token->value) );
 	case CPP_NAME:
		jal_parser_do_trace ( ":%s:", IDENTIFIER_POINTER (token->value) );
	break;

	case CPP_STRING:
 //   case CPP_STRING16:
 //   case CPP_STRING32:
 //   case CPP_WSTRING:
		jal_parser_do_trace ( " \"%s\"", TREE_STRING_POINTER (token->value));
	break;

	default:
		break;
	}
}

/* Return a pointer to the next token from PARSER, reading it in if
necessary.  */

#define jal_parser_peek_token( a ) jal_parser_peek_token_with_line(a, __LINE__, __FUNCTION__ ) 

static inline jal_token *
jal_parser_peek_token_with_line (jal_parser *parser, unsigned int line, const char* func)
{
	if (parser->tokens_avail == 0)
	{
		jal_lex_one_token (parser, &parser->tokens[0]);
		parser->tokens_avail = 1;
	}
	if ( option_parser_trace )
	{
	//	jal_print_identifier (stderr, parser->tokens[0].value , 6);
		jal_parser_do_trace( "   PEEK TOKEN at in function %s(%d): ", func, line);
		jal_print_token (stderr, &parser->tokens[0]);
	}

	return &parser->tokens[0];
}

/* Return true if the next token from PARSER has the indicated
TYPE.  */

static inline bool
jal_parser_next_token_is (jal_parser *parser, enum cpp_ttype type)
{
	return jal_parser_peek_token (parser)->type == type;
}

/* Return true if the next token from PARSER does not have the
indicated TYPE.  */

static inline bool
jal_parser_next_token_is_not (jal_parser *parser, enum cpp_ttype type)
{
	return !jal_parser_next_token_is (parser, type);
}

/* Return true if the next token from PARSER is the indicated
KEYWORD.  */

#define jal_parser_next_token_is_keyword(a,b) jal_parser_next_token_is_keyword_with_line (a, b, __LINE__, __FUNCTION__ )

static inline bool
jal_parser_next_token_is_keyword_with_line (jal_parser *parser, enum rid keyword,unsigned int line, const char* func)
{
	jal_token *token;

	PARSER_TRACE_ENTER();

	/* Peek at the next token.  */
	token = jal_parser_peek_token_with_line (parser, line, func );
	/* Check to see if it is the indicated keyword.  */
	PARSER_TRACE_EXIT();
	return token->keyword == keyword;
}

/* Return true if TOKEN can start a type name,
false otherwise.  */
static bool
jal_token_starts_typename (jal_token *token)
{
	switch (token->type)
	{
	case CPP_NAME:
		switch (token->id_kind)
		{
		case C_ID_ID:
			return false;
		case C_ID_TYPENAME:
			return true;
		case C_ID_CLASSNAME:
			gcc_assert (c_dialect_objc ());
			return true;
		default:
			gcc_unreachable ();
		}
	case CPP_KEYWORD:
		switch (token->keyword)
		{
			// AF TODO Remove later
			case RID_CHAR:
			case RID_SHORT:
			case RID_INT:

			case RID_BIT:
			case RID_BYTE:
			case RID_SBYTE:
			case RID_WORD:
			case RID_SWORD:
			case RID_DWORD:
			case RID_SDWORD:
				return true;
			default:
				return false;
		}
	default:
		return false;
	}
}

/* Return true if the next token from PARSER can start a type name,
false otherwise.  */
static inline bool
jal_parser_next_token_starts_typename (jal_parser *parser)
{
	jal_token *token = jal_parser_peek_token (parser);
	return jal_token_starts_typename (token);
}

/* Return true if TOKEN can start declaration specifiers, false
otherwise.  */
static bool
c_token_starts_declspecs (jal_token *token)
{
	switch (token->type)
	{
	case CPP_NAME:
		switch (token->id_kind)
		{
		case C_ID_ID:
			return false;
		case C_ID_TYPENAME:
			return true;
		case C_ID_CLASSNAME:
			gcc_assert (c_dialect_objc ());
			return true;
		default:
			gcc_unreachable ();
		}
	case CPP_KEYWORD:
		switch (token->keyword)
		{
		case RID_STATIC:
		case RID_EXTERN:
		case RID_REGISTER:
		case RID_TYPEDEF:
		case RID_INLINE:
		case RID_AUTO:
		case RID_THREAD:
		case RID_UNSIGNED:
		case RID_LONG:
		case RID_SHORT:
		case RID_SIGNED:
		case RID_INT:
		case RID_CHAR:
		case RID_FLOAT:
		case RID_DOUBLE:
		case RID_VOID:
		case RID_DFLOAT32:
		case RID_DFLOAT64:
		case RID_DFLOAT128:
		case RID_ENUM:
		case RID_STRUCT:
		case RID_UNION:
		case RID_TYPEOF:
		// case RID_CONST:
		case RID_VOLATILE:
		case RID_RESTRICT:
		case RID_ATTRIBUTE:
		case RID_FRACT:
		case RID_ACCUM:
		case RID_SAT:


			return true;
		default:
			return false;
		}
	case CPP_LESS:
		return false;
	default:
		return false;
	}
}

/* Return true if the next token from PARSER can start declaration
specifiers, false otherwise.  */
static inline bool
jal_parser_next_token_starts_declspecs (jal_parser *parser)
{
	jal_token *token = jal_parser_peek_token (parser);
	return c_token_starts_declspecs (token);
}

/* Return a pointer to the next-but-one token from PARSER, reading it
in if necessary.  The next token is already read in.  */

static jal_token *
jal_parser_peek_2nd_token (jal_parser *parser)
{
	if (parser->tokens_avail >= 2)
		return &parser->tokens[1];
	gcc_assert (parser->tokens_avail == 1);
	gcc_assert (parser->tokens[0].type != CPP_EOF);
	gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
	jal_lex_one_token (parser, &parser->tokens[1]);
	parser->tokens_avail = 2;
	return &parser->tokens[1];
}


#define jal_parser_consume_token( a ) jal_parser_consume_token_with_line(a, __LINE__, __FUNCTION__ ) 

static void
jal_parser_consume_token_with_line (jal_parser *parser, unsigned int line, const char* func);

static void
jal_parser_consume_token_with_line (jal_parser *parser, unsigned int line, const char* func)
{
	gcc_assert (parser->tokens_avail >= 1);
	gcc_assert (parser->tokens[0].type != CPP_EOF);
	gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
	gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);

	if ( option_parser_trace )
	{
	//	jal_print_identifier (stderr, parser->tokens[0].value , 6);
		jal_parser_do_trace( "CONSUMING TOKEN at %s(%d): ", func, line);
		jal_print_token (stderr, &parser->tokens[0]);
		jal_parser_do_trace( "\n");
	}

	if (parser->tokens_avail == 2)
		parser->tokens[0] = parser->tokens[1];
	parser->tokens_avail--;
}

/* Expect the current token to be a #pragma.  Consume it and remember
that we've begun parsing a pragma.  */

static void
jal_parser_consume_pragma (jal_parser *parser)
{
	gcc_assert (!parser->in_pragma);
	gcc_assert (parser->tokens_avail >= 1);
	gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
	if (parser->tokens_avail == 2)
		parser->tokens[0] = parser->tokens[1];
	parser->tokens_avail--;
	parser->in_pragma = true;
}

/* Update the globals input_location and in_system_header from
TOKEN.  */
static inline void
jal_parser_set_source_position_from_token (jal_token *token)
{
	if (token->type != CPP_EOF)
	{
		input_location = token->location;
		//in_system_header = token->in_system_header;
	}
}

/* Issue a diagnostic of the form
FILE:LINE: MESSAGE before TOKEN
where TOKEN is the next token in the input stream of PARSER.
MESSAGE (specified by the caller) is usually of the form "expected
OTHER-TOKEN".

Do not issue a diagnostic if still recovering from an error.

??? This is taken from the C++ parser, but building up messages in
this way is not i18n-friendly and some other approach should be
used.  */

static void
jal_parser_error (jal_parser *parser, const char *gmsgid)
{
	jal_token *token = jal_parser_peek_token (parser);
	if (parser->error)
		return;
	parser->error = true;
	if (!gmsgid)
		return;
	/* This diagnostic makes more sense if it is tagged to the line of
	the token we just peeked at.  */
	jal_parser_set_source_position_from_token (token);

	// AF
	c_parse_error (gmsgid,
		/* Because jal_parse_error does not understand
		CPP_KEYWORD, keywords are treated like
		identifiers.  */
		(token->type == CPP_KEYWORD ? CPP_NAME : token->type),
		token->value);
}

/* If the next token is of the indicated TYPE, consume it.  Otherwise,
issue the error MSGID.  If MSGID is NULL then a message has already
been produced and no message will be produced this time.  Returns
true if found, false otherwise.  */

static bool
jal_parser_require (jal_parser *parser,
					enum cpp_ttype type,
					const char *msgid)
{
	if (jal_parser_next_token_is (parser, type))
	{
		jal_parser_consume_token (parser);
		return true;
	}
	else
	{
		jal_parser_error (parser, msgid);
		return false;
	}
}

/* If the next token is the indicated keyword, consume it.  Otherwise,
issue the error MSGID.  Returns true if found, false otherwise.  */

#define  jal_parser_require_keyword(a,b,c) jal_parser_require_keyword_with_line (a,b,c, __LINE__, __FUNCTION__)  


static bool
jal_parser_require_keyword_with_line (jal_parser *parser,
							enum rid keyword,
							const char *msgid,
							unsigned int line,
							const char* func)
{
	if (jal_parser_next_token_is_keyword_with_line (parser, keyword, line, func))
	{
		jal_parser_consume_token_with_line(parser, line,func);
		return true;
	}
	else
	{
		jal_parser_error (parser, msgid);
		return false;
	}
}

/* Like jal_parser_require, except that tokens will be skipped until the
desired token is found.  An error message is still produced if the
next token is not as expected.  If MSGID is NULL then a message has
already been produced and no message will be produced this
time.  */

static void
jal_parser_skip_until_found (jal_parser *parser,
							 enum cpp_ttype type,
							 const char *msgid)
{
	unsigned nesting_depth = 0;

	if (jal_parser_require (parser, type, msgid))
		return;

	/* Skip tokens until the desired token is found.  */
	while (true)
	{
		/* Peek at the next token.  */
		jal_token *token = jal_parser_peek_token (parser);
		/* If we've reached the token we want, consume it and stop.  */
		if (token->type == type && !nesting_depth)
		{
			jal_parser_consume_token (parser);
			break;
		}

		/* If we've run out of tokens, stop.  */
		if (token->type == CPP_EOF)
			return;
		if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
			return;
		if (token->type == CPP_OPEN_BRACE
			|| token->type == CPP_OPEN_PAREN
			|| token->type == CPP_OPEN_SQUARE)
			++nesting_depth;
		else if (token->type == CPP_CLOSE_BRACE
			|| token->type == CPP_CLOSE_PAREN
			|| token->type == CPP_CLOSE_SQUARE)
		{
			if (nesting_depth-- == 0)
				break;
		}
		/* Consume this token.  */
		jal_parser_consume_token (parser);
	}
	parser->error = false;
}

/* Skip tokens until the end of a parameter is found, but do not
consume the comma, semicolon or closing delimiter.  */

static void
jal_parser_skip_to_end_of_parameter (jal_parser *parser)
{
	unsigned nesting_depth = 0;

	while (true)
	{
		jal_token *token = jal_parser_peek_token (parser);
		if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
			&& !nesting_depth)
			break;
		/* If we've run out of tokens, stop.  */
		if (token->type == CPP_EOF)
			return;
		if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
			return;
		if (token->type == CPP_OPEN_BRACE
			|| token->type == CPP_OPEN_PAREN
			|| token->type == CPP_OPEN_SQUARE)
			++nesting_depth;
		else if (token->type == CPP_CLOSE_BRACE
			|| token->type == CPP_CLOSE_PAREN
			|| token->type == CPP_CLOSE_SQUARE)
		{
			if (nesting_depth-- == 0)
				break;
		}
		/* Consume this token.  */
		jal_parser_consume_token (parser);
	}
	parser->error = false;
}

/* Expect to be at the end of the pragma directive and consume an
end of line marker.  */

static void
jal_parser_skip_to_pragma_eol (jal_parser *parser)
{
	gcc_assert (parser->in_pragma);
	parser->in_pragma = false;

	if (!jal_parser_require (parser, CPP_PRAGMA_EOL, "expected end of line"))
		while (true)
		{
			jal_token *token = jal_parser_peek_token (parser);
			if (token->type == CPP_EOF)
				break;
			if (token->type == CPP_PRAGMA_EOL)
			{
				jal_parser_consume_token (parser);
				break;
			}
			jal_parser_consume_token (parser);
		}

		parser->error = false;
}

/* Skip tokens until we have consumed an entire block, or until we
have consumed a non-nested ';'.  */

static void
jal_parser_skip_to_end_of_block_or_statement (jal_parser *parser)
{
	unsigned nesting_depth = 0;
	bool save_error = parser->error;

	while (true)
	{
		jal_token *token;

		/* Peek at the next token.  */
		token = jal_parser_peek_token (parser);

		switch (token->type)
		{
		case CPP_EOF:
			return;

		case CPP_PRAGMA_EOL:
			if (parser->in_pragma)
				return;
			break;

		//case CPP_SEMICOLON:
		//	/* If the next token is a ';', we have reached the
		//	end of the statement.  */
		//	if (!nesting_depth)
		//	{
		//		/* Consume the ';'.  */
		//		jal_parser_consume_token (parser);
		//		goto finished;
		//	}
		//	break;

		case CPP_CLOSE_BRACE:
			/* If the next token is a non-nested '}', then we have
			reached the end of the current block.  */
			if (nesting_depth == 0 || --nesting_depth == 0)
			{
				jal_parser_consume_token (parser);
				goto finished;
			}
			break;

		case CPP_OPEN_BRACE:
			/* If it the next token is a '{', then we are entering a new
			block.  Consume the entire block.  */
			++nesting_depth;
			break;

		case CPP_PRAGMA:
			/* If we see a pragma, consume the whole thing at once.  We
			have some safeguards against consuming pragmas willy-nilly.
			Normally, we'd expect to be here with parser->error set,
			which disables these safeguards.  But it's possible to get
			here for secondary error recovery, after parser->error has
			been cleared.  */
			jal_parser_consume_pragma (parser);
			jal_parser_skip_to_pragma_eol (parser);
			parser->error = save_error;
			continue;

		default:
			break;
		}

		jal_parser_consume_token (parser);
	}

finished:
	parser->error = false;
}

/* Possibly kinds of declarator to parse.  */
typedef enum c_dtr_syn {
	/* A normal declarator with an identifier.  */
	C_DTR_NORMAL,
	/* An abstract declarator (maybe empty).  */
	C_DTR_ABSTRACT,
	/* A parameter declarator: may be either, but after a type name does
	not redeclare a typedef name as an identifier if it can
	alternatively be interpreted as a typedef name; see DR#009,
	applied in C90 TC1, omitted from C99 and reapplied in C99 TC2
	following DR#249.  For example, given a typedef T, "int T" and
	"int *T" are valid parameter declarations redeclaring T, while
	"int (T)" and "int * (T)" and "int (T[])" and "int (T (int))" are
	abstract declarators rather than involving redundant parentheses;
	the same applies with attributes inside the parentheses before
	"T".  */
	C_DTR_PARM
} c_dtr_syn;


// -------------------------------------------------------------------------------
// FUNCTION PROTOTYPES
// -------------------------------------------------------------------------------

static void jal_parser_alias( jal_parser *parser );

static  void jal_parser_procedure_or_function (	jal_parser *parser, bool is_function, bool nested );


static void jal_parser_var_declaration( jal_parser *parser, bool empty_ok, bool nested, bool start_attr_ok);
static void jal_parser_parse_var_type ( jal_parser *parser, struct jal_declspecs *specs, bool allow_attributes  );

static void jal_parser_compound_statement_nostart (jal_parser *parser);
static tree jal_parser_compound_statement (jal_parser *parser);


static void jal_parser_external_declaration (jal_parser *);
static void jal_parser_asm_definition (jal_parser *);
static void jal_parser_declspecs (jal_parser *, struct jal_declspecs *, bool, bool,
								  bool);
static struct jal_typespec jal_parser_enum_specifier (jal_parser *);
static struct jal_typespec jal_parser_struct_or_union_specifier (jal_parser *);
static tree jal_parser_struct_declaration (jal_parser *);
static struct jal_typespec jal_parser_typeof_specifier (jal_parser *);
static struct jal_declarator *jal_parser_declarator (jal_parser *, bool, c_dtr_syn,
												   bool *);
static struct jal_declarator *jal_parser_direct_declarator (jal_parser *, bool,
														  c_dtr_syn, bool *);
static struct jal_declarator *jal_parser_direct_declarator_inner (jal_parser *,
																bool,
struct jal_declarator *);
static struct jal_arg_info *jal_parser_parms_declarator (jal_parser *, bool, tree);
static struct jal_arg_info *jal_parser_parms_list_declarator (jal_parser *, tree);
static struct jal_parm *jal_parser_parameter_declaration (jal_parser *, tree);
static tree jal_parser_simple_asm_expr (jal_parser *);
static tree jal_parser_attributes (jal_parser *);
static struct jal_type_name *jal_parser_type_name (jal_parser *);
static struct jal_expr jal_parser_initializer (jal_parser *);
static struct jal_expr jal_parser_braced_init (jal_parser *, tree, bool);
static void jal_parser_initelt (jal_parser *);
static void jal_parser_initval (jal_parser *, struct jal_expr *);
static void jal_parser_label (jal_parser *);
static void jal_parser_statement (jal_parser *);
static void jal_parser_statement_after_labels (jal_parser *);
static tree jal_parser_if_statement (jal_parser *, bool isIf);
static void jal_parser_var_delcaration( jal_parser *parser );
static void jal_parser_const_delcaration( jal_parser *parser );
static void jal_parser_case_statement (jal_parser *);
static void jal_parser_while_statement (jal_parser *);
static void jal_parser_repeat_until_statement (jal_parser *);
static void jal_parser_for_statement (jal_parser *);
static void jal_parser_forever_statement (jal_parser *);
static void jal_parser_block_statement( jal_parser *parser );

static tree jal_parser_asm_statement (jal_parser *);
static tree jal_parser_asm_operands (jal_parser *, bool);
static tree jal_parser_asm_clobbers (jal_parser *);
static struct jal_expr jal_parser_expr_no_commas (jal_parser *, struct jal_expr *);
static struct jal_expr jal_parser_binary_expression (jal_parser *, struct jal_expr *);
static struct jal_expr jal_parser_cast_expression (jal_parser *, struct jal_expr *);
static struct jal_expr jal_parser_unary_expression (jal_parser *);
static struct jal_expr jal_parser_sizeof_expression (jal_parser *);
static struct jal_expr jal_parser_alignof_expression (jal_parser *);
static struct jal_expr jal_parser_postfix_expression (jal_parser *);
static struct jal_expr jal_parser_postfix_expression_after_paren_type (jal_parser *,
struct jal_type_name *);
static struct jal_expr jal_parser_postfix_expression_after_primary (jal_parser *,
struct jal_expr);
static struct jal_expr jal_parser_expression (jal_parser *);
static struct jal_expr jal_parser_expression_conv (jal_parser *);
static tree jal_parser_expr_list (jal_parser *, bool);

enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
static bool jal_parser_pragma (jal_parser *, enum pragma_context);
static  void jal_parser_pragma1 ( jal_parser *parser );


/* Parse a translation unit (C90 6.7, C99 6.9).

translation-unit:
external-declarations

external-declarations:
external-declaration
external-declarations external-declaration

GNU extensions:

translation-unit:
empty
*/

static void
jal_parser_translation_unit (jal_parser *parser)
{
	if (!jal_parser_next_token_is (parser, CPP_EOF))
	{
		void *obstack_position = obstack_alloc (&parser_obstack, 0);
		do
		{
			ggc_collect ();
			jal_parser_external_declaration (parser);
			obstack_free (&parser_obstack, obstack_position);
		}
		while (jal_parser_next_token_is_not (parser, CPP_EOF));
	}
}

/* Parse an external declaration (C90 6.7, C99 6.9).

external-declaration:
function-definition
declaration

GNU extensions:

external-declaration:
asm-definition
;
@end
*/

static void
jal_parser_external_declaration (jal_parser *parser)
{
	//int ext;
	switch (jal_parser_peek_token (parser)->type)
	{
	case CPP_KEYWORD:
		switch (jal_parser_peek_token (parser)->keyword)
		{
		default:
			goto decl_or_fndef;
		}
		break;
	case CPP_SEMICOLON:
		//if (pedantic)
		//	pedwarn ("%HISO C does not allow extra %<;%> outside of a function",
		//	&jal_parser_peek_token (parser)->location);
		jal_parser_consume_token (parser);
		break;
	case CPP_PRAGMA:
		jal_parser_pragma (parser, pragma_external);
		break;
	case CPP_PLUS:
	case CPP_MINUS:
		/* Else fall through, and yield a syntax error trying to parse
		as a declaration or function definition.  */
	default:
decl_or_fndef:
		/* A declaration or a function definition.  We can only tell
		which after parsing the declaration specifiers, if any, and
		the first declarator.  */

		// AF TODO, INSERT MAIN INSTEAD?
		jal_parser_procedure_or_function (	parser, true, false );

		break;
	}
}

static 
void jal_parser_pragma1 ( jal_parser *parser )
{
	jal_parser_require_keyword (parser, RID_PRAGMA, "expected %<pragma%>");

	// AF TODO, add check
	if (jal_parser_next_token_is (parser, CPP_NAME))
	{
		printf(  "\nTRACE: MAKE INLINE" );
		make_current_function_inline();
		jal_parser_consume_token (parser);
	}
}


static 
void jal_parser_procedure_or_function (	jal_parser *parser, bool is_function, bool nested )
{
	struct jal_declspecs *specs;
	tree prefix_attrs;
	tree all_prefix_attrs;
	//bool diagnosed_no_specs = false;
	// location_t here = jal_parser_peek_token (parser)->location;
	// bool empty_ok = true;
	//bool start_attr_ok = true;

	if ( is_function )
	{
		jal_parser_require_keyword (parser, RID_FUNCTION, "expected %<function%>");
	}
	else
	{
		jal_parser_require_keyword (parser, RID_PROCEDURE, "expected %<procedure%>");
	}

	specs = build_null_declspecs ();

	jal_parser_trace0(  "jal_parser_procedure 1" );

	pending_xref_error ();
	prefix_attrs = specs->attrs;
	all_prefix_attrs = prefix_attrs;
	specs->attrs = NULL_TREE;

	{
		struct jal_declarator *declarator;
		bool dummy = false;
		tree fnbody;

		jal_parser_trace0(  "jal_parser_procedure_or_function 2" );

		/* Declaring either one or more declarators (in which case we
		should diagnose if there were no declaration specifiers) or a
		function definition (in which case the diagnostic for
		implicit int suffices).  */
		declarator = jal_parser_declarator (parser, specs->type_seen_p,
			C_DTR_NORMAL, &dummy);
		if (declarator == NULL)
		{
			jal_parser_trace0(  "jal_parser_procedure_or_function 3" );
			jal_parser_skip_to_end_of_block_or_statement (parser);
			return;
		}

		/* Function definition (nested or otherwise).  */
		if (nested)
		{
			jal_parser_trace0(  "jal_parser_procedure_or_function 4 Nested function" );
			push_function_context ();
		}

		if ( is_function )
		{
			jal_parser_require_keyword (parser, RID_RETURN, "expected %<return%>");
			jal_parser_trace0(  "jal_parser_procedure 5a is function, parse type" );
			jal_parser_parse_var_type ( parser, specs, false );
			jal_parser_trace0(  "jal_parser_procedure 5b is function, parsed type" );
		}
		else
		{
			struct jal_typespec t;
			jal_parser_trace0(  "jal_parser_procedure 5 PROCEDURE MAKE VOID" );
			t.kind = ctsk_resword;
			t.spec = get_identifier( "void" );
			declspecs_add_type( specs, t );
		}

		if (parser->error)
		{
			jal_parser_skip_to_end_of_block_or_statement (parser);
			return;
		}

		if (nested && !specs->declspecs_seen_p)
		{
			jal_parser_error (parser, "jal_parser_procedure_or_function 6 expected declaration specifiers");
			jal_parser_skip_to_end_of_block_or_statement (parser);
			return;
		}

		finish_declspecs (specs);

		//if ( jal_parser_next_token_is_keyword (parser, RID_IS ) )
		//{
		//	tree asm_name = NULL_TREE;
		//	tree postfix_attrs = NULL_TREE;
		//	jal_parser_trace0(  "jal_parser_procedure_or_function 7" );
		//	if (!diagnosed_no_specs && !specs->declspecs_seen_p)
		//	{
		//		diagnosed_no_specs = true;
		//		//pedwarn ("%Hdata definition has no type or storage class",
		//		//	&here);
		//	}
		//	/* Having seen a data definition, there cannot now be a
		//	function definition.  */

		//	{
		//		tree d = start_decl (declarator, specs, false,
		//			chainon (postfix_attrs,
		//			all_prefix_attrs));
		//		if (d)
		//			finish_decl (d, NULL_TREE, asm_name);

		//		jal_parser_trace0(  "jal_parser_procedure_or_function 8" );
		//	}
		//}
		//else
		{
			jal_parser_trace0(  "jal_parser_procedure_or_function 9" );
			if (!start_function (specs, declarator, all_prefix_attrs))
			{
				jal_parser_trace0(  "jal_parser_procedure_or_function 10" );

				/* This can appear in many cases looking nothing like a
				function definition, so we don't give a more specific
				error suggesting there was one.  */
				jal_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
					"or %<__attribute__%>");
				if (nested)
					pop_function_context ();
				return;
			}

			jal_parser_require_keyword (parser, RID_IS, "expected %<is%>");

			jal_parser_trace0(  "jal_parser_procedure_or_function 11 " );

			DECL_SOURCE_LOCATION (current_function_decl) = jal_parser_peek_token (parser)->location;
			store_parm_decls ();
			
			fnbody = jal_parser_compound_statement (parser);


			if ( is_function )
			{
				jal_parser_require_keyword (parser, RID_FUNCTION, "expected %<end function%>");
			}
			else
			{
				jal_parser_require_keyword (parser, RID_PROCEDURE, "expected %<end procedure%>");
			}

			if (nested)
			{
				tree decl = current_function_decl;
				jal_parser_trace0(  "jal_parser_procedure_or_function 100" );
				add_stmt (fnbody);
				finish_function ();
				pop_function_context ();
				add_stmt (build_stmt (DECL_EXPR, decl));
			}
			else
			{
				jal_parser_trace0(  "jal_parser_procedure_or_function 101" );
				add_stmt (fnbody);
				finish_function ();
			}
		}
	}
}




/* Parse an asm-definition (asm() outside a function body).  This is a
GNU extension.

asm-definition:
simple-asm-expr ;
*/

static void
jal_parser_asm_definition (jal_parser *parser)
{
	tree asm_str = jal_parser_simple_asm_expr (parser);
	if (asm_str)
		cgraph_add_asm_node (asm_str);
	jal_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}

/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
6.7), adding them to SPECS (which may already include some).
Storage class specifiers are accepted iff SCSPEC_OK; type
specifiers are accepted iff TYPESPEC_OK; attributes are accepted at
the start iff START_ATTR_OK.

declaration-specifiers:
storage-class-specifier declaration-specifiers[opt]
type-specifier declaration-specifiers[opt]
type-qualifier declaration-specifiers[opt]
function-specifier declaration-specifiers[opt]

Function specifiers (inline) are from C99, and are currently
handled as storage class specifiers, as is __thread.

C90 6.5.1, C99 6.7.1:
storage-class-specifier:
typedef
extern
static
auto
register

C99 6.7.4:
function-specifier:
inline

C90 6.5.2, C99 6.7.2:
type-specifier:
void
char
short
int
long
float
double
signed
unsigned
_Bool
_Complex
[_Imaginary removed in C99 TC2]
struct-or-union-specifier
enum-specifier
typedef-name

(_Bool and _Complex are new in C99.)

C90 6.5.3, C99 6.7.3:

type-qualifier:
const
restrict
volatile

(restrict is new in C99.)

GNU extensions:

declaration-specifiers:
attributes declaration-specifiers[opt]

storage-class-specifier:
__thread

type-specifier:
typeof-specifier
_Decimal32
_Decimal64
_Decimal128
_Fract
_Accum
_Sat

(_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)

Objective-C:

type-specifier:
class-name objc-protocol-refs[opt]
typedef-name objc-protocol-refs
objc-protocol-refs
*/

static void jal_parser_parse_var_type ( jal_parser *parser, struct jal_declspecs *specs, bool allow_attributes )
{
	struct jal_typespec t;
	//tree attrs;

	jal_parser_trace0(  "TRACE: jal_parser_parse_var_type " );

	if ( jal_parser_peek_token (parser)->keyword == RID_VOLATILE )
	{
		if ( allow_attributes )
		{
			jal_parser_trace0(  "TRACE: jal_parser_parse_var_type is VOLATILE " );
			declspecs_add_qual (specs, jal_parser_peek_token (parser)->value);
			jal_parser_consume_token (parser);
		}
		else
		{
			jal_parser_error (parser, "volatile atribute is not allowed");
			jal_parser_consume_token (parser);
		}
	}

	// AF TODO, array stuff and byte*N stuff + BIT stuff
	switch (jal_parser_peek_token (parser)->keyword)
	{
		case RID_SHORT:
		case RID_INT:
		case RID_CHAR:
		case RID_WORD:
		case RID_SWORD:
		case RID_BYTE:
		case RID_SBYTE:
		case RID_DWORD:
		case RID_SDWORD:
			jal_parser_trace0(  " TRACE: jal_parser_parse_var_type GOT KNOWN TYPE" );

			t.kind = ctsk_resword;
			t.spec = jal_parser_peek_token (parser)->value;

			declspecs_add_type (specs, t);
			jal_parser_consume_token (parser);
			break;
		default:
			jal_parser_error (parser, "expected variable type");
			break;
	}
	jal_parser_trace0(  "TRACE: jal_parser_parse_var_type DONE " );
}

static int loop_var_idx = 0;
char loop_var_string[255];

tree make_implicit_var(jal_parser *parser, const char* tpname);

tree make_implicit_var(jal_parser *parser, const char* tpname)
{
	struct jal_declspecs *specs;
	struct jal_declarator *declarator;
	tree asm_name = NULL_TREE;
	tree postfix_attrs = NULL_TREE;
	tree all_prefix_attrs= NULL_TREE;
	tree d ;

	tree var_id;
	tree var_type;

	struct jal_typespec t;
	//struct jal_expr init;

	jal_parser_trace0(  "make_implicit_var ENTRY" );

	var_type = get_identifier( tpname);

	jal_parser_trace0(  "make_implicit_var 1" );
	sprintf( loop_var_string, "__JAL_IMPLICIT_VAR_%d",  loop_var_idx++ );
	jal_parser_trace0(  "make_implicit_var 2" );

	var_id = get_identifier( loop_var_string );

	specs = build_null_declspecs ();

	t.kind = ctsk_resword;
	t.spec = var_type;
	// jal_parser_peek_token (parser)->value;

	// specs->unsigned_p = true;
	//C_SET_RID_CODE( t.spec ,RID_SHORT );

	//declspecs_add_scspec (specs, rijal_parser_peek_token (parser)->value);
	declspecs_add_type (specs, t);
	finish_declspecs (specs);

	specs->attrs = NULL_TREE;


	declarator = build_id_declarator (var_id);
	declarator->id_loc = jal_parser_peek_token (parser)->location;

	jal_parser_trace0(  "make_implicit_var 3" );

	d = start_decl (declarator, specs, false, chainon (postfix_attrs, all_prefix_attrs) );
	if (d)
	{
		finish_decl (d, NULL_TREE, asm_name);
	}


	jal_parser_trace0(  "make_implicit_var EXIT" );
	return d;
}


static void jal_parser_declspecs (jal_parser *parser, struct jal_declspecs *specs, bool scspec_ok, bool typespec_ok, bool start_attr_ok)
{
	bool attrs_ok = start_attr_ok;
	bool seen_type = specs->type_seen_p;

	jal_parser_trace0(  "jal_parser_declspecs 1" );

	while ( jal_parser_next_token_is (parser, CPP_NAME) || jal_parser_next_token_is (parser, CPP_KEYWORD) )
	{
		struct jal_typespec t;
		tree attrs;

		jal_parser_trace0(  "jal_parser_declspecs LOOP 2" );

		if (jal_parser_next_token_is (parser, CPP_NAME))
		{
			tree value = jal_parser_peek_token (parser)->value;
			c_id_kind kind = jal_parser_peek_token (parser)->id_kind;
			/* This finishes the specifiers unless a type name is OK, it
			is declared as a type name and a type name hasn't yet
			been seen.  */

			jal_parser_trace0(  "jal_parser_declspecs 3" );

			if (!typespec_ok || seen_type
				|| (kind != C_ID_TYPENAME && kind != C_ID_CLASSNAME))
				break;
			jal_parser_consume_token (parser);
			seen_type = true;
			attrs_ok = true;
			if (kind == C_ID_TYPENAME
				&& (!c_dialect_objc ()
				|| jal_parser_next_token_is_not (parser, CPP_LESS)))
			{
				t.kind = ctsk_typedef;
				/* For a typedef name, record the meaning, not the name.
				In case of 'foo foo, bar;'.  */
				t.spec = lookup_name (value);
				jal_parser_trace0(  "jal_parser_declspecs 4" );

			}
			else
			{
				jal_parser_trace0(  "jal_parser_declspecs 5" );

			}
			declspecs_add_type (specs, t);
			jal_parser_trace0(  "jal_parser_declspecs 6" );

			continue;
		}
		if (jal_parser_next_token_is (parser, CPP_LESS))
		{
		}

		gcc_assert (jal_parser_next_token_is (parser, CPP_KEYWORD));

		switch (jal_parser_peek_token (parser)->keyword)
		{
		case RID_STATIC:
		case RID_EXTERN:
		case RID_REGISTER:
		case RID_TYPEDEF:
		case RID_INLINE:
		case RID_AUTO:
		case RID_THREAD:
			if (!scspec_ok)
				goto out;
			attrs_ok = true;
			/* TODO: Distinguish between function specifiers (inline)
			and storage class specifiers, either here or in
			declspecs_add_scspec.  */
			jal_parser_trace0(  "jal_parser_declspecs LOOP 8" );

			declspecs_add_scspec (specs, jal_parser_peek_token (parser)->value);
			jal_parser_consume_token (parser);
			break;
		case RID_UNSIGNED:
		case RID_LONG:
		case RID_SHORT:
		case RID_SIGNED:
		case RID_INT:
		case RID_CHAR:
		case RID_FLOAT:
		case RID_DOUBLE:
		case RID_VOID:
		case RID_DFLOAT32:
		case RID_DFLOAT64:
		case RID_DFLOAT128:
		case RID_FRACT:
		case RID_ACCUM:
		case RID_SAT:
		case RID_BYTE:
		case RID_SBYTE:
		case RID_WORD:
		case RID_SWORD:
		case RID_DWORD:
		case RID_SDWORD:

			jal_parser_trace0(  "jal_parser_declspecs 9" );

			if (!typespec_ok)
				goto out;
			attrs_ok = true;
			seen_type = true;
			if (c_dialect_objc ())
				parser->objc_need_raw_identifier = true;
			t.kind = ctsk_resword;
			t.spec = jal_parser_peek_token (parser)->value;
			
			jal_parser_trace(  "FOUND TYPE, set to :%d: !!", t.spec);

			declspecs_add_type (specs, t);
			jal_parser_consume_token (parser);
			break;
		case RID_ENUM:
			if (!typespec_ok)
				goto out;
			attrs_ok = true;
			seen_type = true;
			t = jal_parser_enum_specifier (parser);
			declspecs_add_type (specs, t);
			break;
		case RID_STRUCT:
		case RID_UNION:
			if (!typespec_ok)
				goto out;
			attrs_ok = true;
			seen_type = true;
			t = jal_parser_struct_or_union_specifier (parser);
			declspecs_add_type (specs, t);
			break;
		case RID_TYPEOF:
			/* ??? The old parser rejected typeof after other type
			specifiers, but is a syntax error the best way of
			handling this?  */
			if (!typespec_ok || seen_type)
				goto out;
			attrs_ok = true;
			seen_type = true;
			t = jal_parser_typeof_specifier (parser);
			declspecs_add_type (specs, t);
			break;
		//case RID_CONST:
		case RID_VOLATILE:
		//case RID_RESTRICT:
			jal_parser_trace0(  "jal_parser_declspecs VOLATILE " );

			attrs_ok = true;
			declspecs_add_qual (specs, jal_parser_peek_token (parser)->value);
			jal_parser_consume_token (parser);
		//	
		//	jal_parser_var_declaration(parser, true, true, true);
		//	// 
		//	
			break;
		case RID_ATTRIBUTE:
			if (!attrs_ok)
				goto out;
			attrs = jal_parser_attributes (parser);
			declspecs_add_attrs (specs, attrs);
			break;
		default:
			goto out;
		}
	}
out: ;
}

/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2).

enum-specifier:
enum attributes[opt] identifier[opt] { enumerator-list } attributes[opt]
enum attributes[opt] identifier[opt] { enumerator-list , } attributes[opt]
enum attributes[opt] identifier

The form with trailing comma is new in C99.  The forms with
attributes are GNU extensions.  In GNU C, we accept any expression
without commas in the syntax (assignment expressions, not just
conditional expressions); assignment expressions will be diagnosed
as non-constant.

enumerator-list:
enumerator
enumerator-list , enumerator

enumerator:
enumeration-constant
enumeration-constant = constant-expression
*/

static struct jal_typespec
jal_parser_enum_specifier (jal_parser *parser)
{
	struct jal_typespec ret;
	tree attrs;
	tree ident = NULL_TREE;
	location_t ident_loc;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_ENUM));
	jal_parser_consume_token (parser);
	attrs = jal_parser_attributes (parser);
	/* Set the location in case we create a decl now.  */
	jal_parser_set_source_position_from_token (jal_parser_peek_token (parser));
	if (jal_parser_next_token_is (parser, CPP_NAME))
	{
		ident = jal_parser_peek_token (parser)->value;
		ident_loc = jal_parser_peek_token (parser)->location;
		jal_parser_consume_token (parser);
	}
	if (jal_parser_next_token_is (parser, CPP_OPEN_BRACE))
	{
		/* Parse an enum definition.  */
		struct jal_enum_contents the_enum;
		tree type = start_enum (&the_enum, ident);
		tree postfix_attrs;
		/* We chain the enumerators in reverse order, then put them in
		forward order at the end.  */
		tree values = NULL_TREE;
		jal_parser_consume_token (parser);
		while (true)
		{
			tree enum_id;
			tree enum_value;
			tree enum_decl;
			bool seen_comma;
			jal_token *token;
			  location_t comma_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
			  location_t value_loc;

			if (jal_parser_next_token_is_not (parser, CPP_NAME))
			{
				jal_parser_error (parser, "expected identifier");
				jal_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
				values = error_mark_node;
				break;
			}
			token = jal_parser_peek_token (parser);
			enum_id = token->value;
			/* Set the location in case we create a decl now.  */
			jal_parser_set_source_position_from_token (token);
			jal_parser_consume_token (parser);
			value_loc = token->location;
	
			if (jal_parser_next_token_is (parser, CPP_EQ))
			{
				jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM A" );
				enum_value = jal_parser_expr_no_commas (parser, NULL).value;
			}
			else
				enum_value = NULL_TREE;
			enum_decl = build_enumerator (&the_enum, enum_id, enum_value, value_loc);
			TREE_CHAIN (enum_decl) = values;
			values = enum_decl;
			seen_comma = false;
			if (jal_parser_next_token_is (parser, CPP_COMMA))
			{
				comma_loc = jal_parser_peek_token (parser)->location;
				seen_comma = true;
				jal_parser_consume_token (parser);
			}
			if (jal_parser_next_token_is (parser, CPP_CLOSE_BRACE))
			{
				//if (seen_comma && pedantic && !flag_isoc99)
				//	pedwarn ("%Hcomma at end of enumerator list", &comma_loc);
				jal_parser_consume_token (parser);
				break;
			}
			if (!seen_comma)
			{
				jal_parser_error (parser, "expected %<,%> or %<}%>");
				jal_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
				values = error_mark_node;
				break;
			}
		}
		postfix_attrs = jal_parser_attributes (parser);
		ret.spec = finish_enum (type, nreverse (values),
			chainon (attrs, postfix_attrs));
		ret.kind = ctsk_tagdef;
		return ret;
	}
	else if (!ident)
	{
		jal_parser_error (parser, "expected %<{%>");
		ret.spec = error_mark_node;
		ret.kind = ctsk_tagref;
		return ret;
	}
	ret = parser_xref_tag (ENUMERAL_TYPE, ident);
	/* In ISO C, enumerated types can be referred to only if already
	defined.  */
	if (pedantic && !COMPLETE_TYPE_P (ret.spec))
	{
		gcc_assert (ident);
		//pedwarn ("%HISO C forbids forward references to %<enum%> types",
		//	&ident_loc);
	}
	return ret;
}

/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1).

struct-or-union-specifier:
struct-or-union attributes[opt] identifier[opt]
{ struct-contents } attributes[opt]
struct-or-union attributes[opt] identifier

struct-contents:
struct-declaration-list

struct-declaration-list:
struct-declaration ;
struct-declaration-list struct-declaration ;

GNU extensions:

struct-contents:
empty
struct-declaration
struct-declaration-list struct-declaration

struct-declaration-list:
struct-declaration-list ;
;

(Note that in the syntax here, unlike that in ISO C, the semicolons
are included here rather than in struct-declaration, in order to
describe the syntax with extra semicolons and missing semicolon at
end.)

Objective-C:

struct-declaration-list:
@defs ( class-name )

(Note this does not include a trailing semicolon, but can be
followed by further declarations, and gets a pedwarn-if-pedantic
when followed by a semicolon.)  */

static struct jal_typespec
jal_parser_struct_or_union_specifier (jal_parser *parser)
{
	struct jal_typespec ret;
	tree attrs;
	tree ident = NULL_TREE;
	enum tree_code code;
	switch (jal_parser_peek_token (parser)->keyword)
	{
	case RID_STRUCT:
		code = RECORD_TYPE;
		break;
	case RID_UNION:
		code = UNION_TYPE;
		break;
	default:
		gcc_unreachable ();
	}
	jal_parser_consume_token (parser);
	attrs = jal_parser_attributes (parser);
	/* Set the location in case we create a decl now.  */
	jal_parser_set_source_position_from_token (jal_parser_peek_token (parser));
	if (jal_parser_next_token_is (parser, CPP_NAME))
	{
		ident = jal_parser_peek_token (parser)->value;
		jal_parser_consume_token (parser);
	}
	if (jal_parser_next_token_is (parser, CPP_OPEN_BRACE))
	{
		/* Parse a struct or union definition.  Start the scope of the
		tag before parsing components.  */
		tree type = start_struct (code, ident);
		tree postfix_attrs;
		/* We chain the components in reverse order, then put them in
		forward order at the end.  Each struct-declaration may
		declare multiple components (comma-separated), so we must use
		chainon to join them, although when parsing each
		struct-declaration we can use TREE_CHAIN directly.

		The theory behind all this is that there will be more
		semicolon separated fields than comma separated fields, and
		so we'll be minimizing the number of node traversals required
		by chainon.  */
		tree contents = NULL_TREE;
		jal_parser_consume_token (parser);
		/* Parse the struct-declarations and semicolons.  Problems with
		semicolons are diagnosed here; empty structures are diagnosed
		elsewhere.  */
		while (true)
		{
			tree decls;
			/* Parse any stray semicolon.  */
			if (jal_parser_next_token_is (parser, CPP_SEMICOLON))
			{
				//if (pedantic)
				//	pedwarn ("%Hextra semicolon in struct or union specified",
				//	&jal_parser_peek_token (parser)->location);
				jal_parser_consume_token (parser);
				continue;
			}
			/* Stop if at the end of the struct or union contents.  */
			if (jal_parser_next_token_is (parser, CPP_CLOSE_BRACE))
			{
				jal_parser_consume_token (parser);
				break;
			}
			/* Accept #pragmas at struct scope.  */
			if (jal_parser_next_token_is (parser, CPP_PRAGMA))
			{
				jal_parser_pragma (parser, pragma_external);
				continue;
			}
			/* Parse some comma-separated declarations, but not the
			trailing semicolon if any.  */
			decls = jal_parser_struct_declaration (parser);
			contents = chainon (decls, contents);
			/* If no semicolon follows, either we have a parse error or
			are at the end of the struct or union and should
			pedwarn.  */
			if (jal_parser_next_token_is (parser, CPP_SEMICOLON))
				jal_parser_consume_token (parser);
			else
			{
				if (jal_parser_next_token_is (parser, CPP_CLOSE_BRACE))
				{
					// pedwarn ("%Hno semicolon at end of struct or union",
					// &jal_parser_peek_token (parser)->location);
				}
				else
				{
					jal_parser_error (parser, "expected %<;%>");
					jal_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
					break;
				}
			}
		}
		postfix_attrs = jal_parser_attributes (parser);
		ret.spec = finish_struct (type, nreverse (contents),
			chainon (attrs, postfix_attrs));
		ret.kind = ctsk_tagdef;
		return ret;
	}
	else if (!ident)
	{
		jal_parser_error (parser, "expected %<{%>");
		ret.spec = error_mark_node;
		ret.kind = ctsk_tagref;
		return ret;
	}
	ret = parser_xref_tag (code, ident);
	return ret;
}

/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1), *without*
the trailing semicolon.

struct-declaration:
specifier-qualifier-list struct-declarator-list

specifier-qualifier-list:
type-specifier specifier-qualifier-list[opt]
type-qualifier specifier-qualifier-list[opt]
attributes specifier-qualifier-list[opt]

struct-declarator-list:
struct-declarator
struct-declarator-list , attributes[opt] struct-declarator

struct-declarator:
declarator attributes[opt]
declarator[opt] : constant-expression attributes[opt]

GNU extensions:

struct-declaration:
__extension__ struct-declaration
specifier-qualifier-list

Unlike the ISO C syntax, semicolons are handled elsewhere.  The use
of attributes where shown is a GNU extension.  In GNU C, we accept
any expression without commas in the syntax (assignment
expressions, not just conditional expressions); assignment
expressions will be diagnosed as non-constant.  */



static tree
jal_parser_struct_declaration (jal_parser *parser)
{
	struct jal_declspecs *specs;
	tree prefix_attrs;
	tree all_prefix_attrs;
	tree decls;
	location_t decl_loc;
	specs = build_null_declspecs ();
	decl_loc = jal_parser_peek_token (parser)->location;

	jal_parser_trace0(  "jal_parser_declspecs C1" );

	jal_parser_declspecs (parser, specs, false, true, true);
	if (parser->error)
		return NULL_TREE;
	if (!specs->declspecs_seen_p)
	{
		jal_parser_error (parser, "expected specifier-qualifier-list");
		return NULL_TREE;
	}
	finish_declspecs (specs);
	if (jal_parser_next_token_is (parser, CPP_SEMICOLON))
	{
		tree ret;
		if (!specs->type_seen_p)
		{
			//if (pedantic)
			//	pedwarn ("%HISO C forbids member declarations with no members",
			//	&decl_loc);
			shadow_tag_warned (specs, pedantic);
			ret = NULL_TREE;
		}
		else
		{
			/* Support for unnamed structs or unions as members of
			structs or unions (which is [a] useful and [b] supports
			MS P-SDK).  */
			tree attrs = NULL;
			ret = grokfield (jal_parser_peek_token (parser)->location, build_id_declarator (NULL_TREE), specs,
				NULL_TREE, &attrs);
			if (ret)
				decl_attributes (&ret, attrs, 0);
		}
		return ret;
	}
	pending_xref_error ();
	prefix_attrs = specs->attrs;
	all_prefix_attrs = prefix_attrs;
	specs->attrs = NULL_TREE;
	decls = NULL_TREE;
	while (true)
	{
		/* Declaring one or more declarators or un-named bit-fields.  */
		struct jal_declarator *declarator;
		bool dummy = false;
		if (jal_parser_next_token_is (parser, CPP_COLON))
			declarator = build_id_declarator (NULL_TREE);
		else
			declarator = jal_parser_declarator (parser, specs->type_seen_p,
			C_DTR_NORMAL, &dummy);
		if (declarator == NULL)
		{
			jal_parser_skip_to_end_of_block_or_statement (parser);
			break;
		}
		if (jal_parser_next_token_is (parser, CPP_COLON)
			|| jal_parser_next_token_is (parser, CPP_COMMA)
			|| jal_parser_next_token_is (parser, CPP_SEMICOLON)
			|| jal_parser_next_token_is (parser, CPP_CLOSE_BRACE)
			|| jal_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
		{
			tree postfix_attrs = NULL_TREE;
			tree width = NULL_TREE;
			tree d;
			if (jal_parser_next_token_is (parser, CPP_COLON))
			{
				jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM B" );

				width = jal_parser_expr_no_commas (parser, NULL).value;
			}
			if (jal_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
				postfix_attrs = jal_parser_attributes (parser);
			d = grokfield (jal_parser_peek_token (parser)->location, declarator, specs, width, &all_prefix_attrs);
			decl_attributes (&d, chainon (postfix_attrs,
				all_prefix_attrs), 0);
			TREE_CHAIN (d) = decls;
			decls = d;
			if (jal_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
				all_prefix_attrs = chainon (jal_parser_attributes (parser),
				prefix_attrs);
			else
				all_prefix_attrs = prefix_attrs;
			if (jal_parser_next_token_is (parser, CPP_COMMA))
				jal_parser_consume_token (parser);
			else if (jal_parser_next_token_is (parser, CPP_SEMICOLON)
				|| jal_parser_next_token_is (parser, CPP_CLOSE_BRACE))
			{
				/* Semicolon consumed in caller.  */
				break;
			}
			else
			{
				jal_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
				break;
			}
		}
		else
		{
			jal_parser_error (parser,
				"expected %<:%>, %<,%>, %<;%>, %<}%> or "
				"%<__attribute__%>");
			break;
		}
	}
	return decls;
}

/* Parse a typeof specifier (a GNU extension).

typeof-specifier:
typeof ( expression )
typeof ( type-name )
*/

static struct jal_typespec
jal_parser_typeof_specifier (jal_parser *parser)
{
	struct jal_typespec ret;
	ret.kind = ctsk_typeof;
	ret.spec = error_mark_node;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_TYPEOF));
	jal_parser_consume_token (parser);
	skip_evaluation++;
	in_typeof++;
	if (!jal_parser_require (parser, CPP_OPEN_PAREN, "5 expected %<(%>"))
	{
		skip_evaluation--;
		in_typeof--;
		return ret;
	}
	if (jal_parser_next_token_starts_typename (parser))
	{
		struct jal_type_name *type = jal_parser_type_name (parser);
		skip_evaluation--;
		in_typeof--;
		if (type != NULL)
		{
			ret.spec = groktypename (type);
			pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
		}
	}
	else
	{
		bool was_vm;
		location_t here = jal_parser_peek_token (parser)->location;
		struct jal_expr expr = jal_parser_expression (parser);
		skip_evaluation--;
		in_typeof--;
		if (TREE_CODE (expr.value) == COMPONENT_REF
			&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
			error ("%H%<typeof%> applied to a bit-field", &here);
		ret.spec = TREE_TYPE (expr.value);
		was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
		/* This should be returned with the type so that when the type
		is evaluated, this can be evaluated.  For now, we avoid
		evaluation when the context might.  */
		if (!skip_evaluation && was_vm)
		{
			tree e = expr.value;

			/* If the expression is not of a type to which we cannot assign a line
			number, wrap the thing in a no-op NOP_EXPR.  */
			if (DECL_P (e) || CONSTANT_CLASS_P (e))
				e = build1 (NOP_EXPR, void_type_node, e);

			if (CAN_HAVE_LOCATION_P (e))
				SET_EXPR_LOCATION (e, input_location);

			add_stmt (e);
		}
		pop_maybe_used (was_vm);
	}
	jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "8 expected %<)%>");
	return ret;
}

/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
6.5.5, C99 6.7.5, 6.7.6).  If TYPE_SEEN_P then a typedef name may
be redeclared; otherwise it may not.  KIND indicates which kind of
declarator is wanted.  Returns a valid declarator except in the
case of a syntax error in which case NULL is returned.  *SEEN_ID is
set to true if an identifier being declared is seen; this is used
to diagnose bad forms of abstract array declarators and to
determine whether an identifier list is syntactically permitted.

declarator:
pointer[opt] direct-declarator

direct-declarator:
identifier
( attributes[opt] declarator )
direct-declarator array-declarator
direct-declarator ( parameter-type-list )
direct-declarator ( identifier-list[opt] )

pointer:
* type-qualifier-list[opt]
* type-qualifier-list[opt] pointer

type-qualifier-list:
type-qualifier
attributes
type-qualifier-list type-qualifier
type-qualifier-list attributes

parameter-type-list:
parameter-list
parameter-list , ...

parameter-list:
parameter-declaration
parameter-list , parameter-declaration

parameter-declaration:
declaration-specifiers declarator attributes[opt]
declaration-specifiers abstract-declarator[opt] attributes[opt]

identifier-list:
identifier
identifier-list , identifier

abstract-declarator:
pointer
pointer[opt] direct-abstract-declarator

direct-abstract-declarator:
( attributes[opt] abstract-declarator )
direct-abstract-declarator[opt] array-declarator
direct-abstract-declarator[opt] ( parameter-type-list[opt] )

GNU extensions:

direct-declarator:
direct-declarator ( parameter-forward-declarations
parameter-type-list[opt] )

direct-abstract-declarator:
direct-abstract-declarator[opt] ( parameter-forward-declarations
parameter-type-list[opt] )

parameter-forward-declarations:
parameter-list ;
parameter-forward-declarations parameter-list ;

The uses of attributes shown above are GNU extensions.

Some forms of array declarator are not included in C99 in the
syntax for abstract declarators; these are disallowed elsewhere.
This may be a defect (DR#289).

This function also accepts an omitted abstract declarator as being
an abstract declarator, although not part of the formal syntax.  */

static struct jal_declarator *
jal_parser_declarator (jal_parser *parser, bool type_seen_p, c_dtr_syn kind,
					   bool *seen_id)
{
	jal_parser_trace(  "jal_parser_declarator 1, seen P is %d OK?", type_seen_p );

	/* Parse any initial pointer part.  */
	if (jal_parser_next_token_is (parser, CPP_MULT))
	{
		struct jal_declspecs *quals_attrs = build_null_declspecs ();
		struct jal_declarator *inner;
		
		jal_parser_trace0(  "jal_parser_declarator CPP MULT " );
		
		jal_parser_consume_token (parser);
		jal_parser_trace0(  "jal_parser_declarator 2" );

		jal_parser_declspecs (parser, quals_attrs, false, false, true);
		inner = jal_parser_declarator (parser, type_seen_p, kind, seen_id);
		if (inner == NULL)
			return NULL;
		else
		{
			jal_parser_trace0( "MAKE POINTER DECLARATION @@@@!!!!!!");
			return make_pointer_declarator (quals_attrs, inner);
		}
	}
	/* Now we have a direct declarator, direct abstract declarator or
	nothing (which counts as a direct abstract declarator here).  */
	jal_parser_trace0(  "jal_parser_declarator 3" );
	return jal_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
}




/* Parse a direct declarator or direct abstract declarator; arguments
as jal_parser_declarator.  */

static struct jal_declarator *
jal_parser_direct_declarator (jal_parser *parser, bool type_seen_p, c_dtr_syn kind,
							  bool *seen_id)
{
	/* The direct declarator must start with an identifier (possibly
	omitted) or a parenthesized declarator (possibly abstract).  In
	an ordinary declarator, initial parentheses must start a
	parenthesized declarator.  In an abstract declarator or parameter
	declarator, they could start a parenthesized declarator or a
	parameter list.  To tell which, the open parenthesis and any
	following attributes must be read.  If a declaration specifier
	follows, then it is a parameter list; if the specifier is a
	typedef name, there might be an ambiguity about redeclaring it,
	which is resolved in the direction of treating it as a typedef
	name.  If a close parenthesis follows, it is also an empty
	parameter list, as the syntax does not permit empty abstract
	declarators.  Otherwise, it is a parenthesized declarator (in
	which case the analysis may be repeated inside it, recursively).

	??? There is an ambiguity in a parameter declaration "int
	(__attribute__((foo)) x)", where x is not a typedef name: it
	could be an abstract declarator for a function, or declare x with
	parentheses.  The proper resolution of this ambiguity needs
	documenting.  At present we follow an accident of the old
	parser's implementation, whereby the first parameter must have
	some declaration specifiers other than just attributes.  Thus as
	a parameter declaration it is treated as a parenthesized
	parameter named x, and as an abstract declarator it is
	rejected.

	??? Also following the old parser, attributes inside an empty
	parameter list are ignored, making it a list not yielding a
	prototype, rather than giving an error or making it have one
	parameter with implicit type int.

	??? Also following the old parser, typedef names may be
	redeclared in declarators, but not Objective-C class names.  */

	jal_parser_trace0(  " jal_parser_direct_declarator 1 ");
	if (kind != C_DTR_ABSTRACT
		&& jal_parser_next_token_is (parser, CPP_NAME)
		&& ((type_seen_p
		&& jal_parser_peek_token (parser)->id_kind == C_ID_TYPENAME)
		|| jal_parser_peek_token (parser)->id_kind == C_ID_ID))
	{

		struct jal_declarator *inner
			= build_id_declarator (jal_parser_peek_token (parser)->value);
		jal_parser_trace(  "BUILDed build_id_declarator of :%d: !!", jal_parser_peek_token (parser)->value);

		*seen_id = true;
		inner->id_loc = jal_parser_peek_token (parser)->location;
		jal_parser_consume_token (parser);
		return jal_parser_direct_declarator_inner (parser, *seen_id, inner);
	}

	if (kind != C_DTR_NORMAL
		&& jal_parser_next_token_is (parser, CPP_OPEN_SQUARE))
	{
		struct jal_declarator *inner = build_id_declarator (NULL_TREE);
		jal_parser_trace0(  " jal_parser_direct_declarator 2 ");

		return jal_parser_direct_declarator_inner (parser, *seen_id, inner);
	}

	/* Either we are at the end of an abstract declarator, or we have
	parentheses.  */

	if ( g_isInCast == false && jal_parser_next_token_is (parser, CPP_OPEN_PAREN))
	{
		tree attrs;
		struct jal_declarator *inner;
		jal_parser_consume_token (parser);
		attrs = jal_parser_attributes (parser);

		jal_parser_trace0(  " jal_parser_direct_declarator 3 ");

		if (kind != C_DTR_NORMAL
			&& (jal_parser_next_token_starts_declspecs (parser)
			|| jal_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
		{
			struct jal_arg_info *args
				= jal_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
				attrs);
	jal_parser_trace0(  " jal_parser_direct_declarator 4 ");

			if (args == NULL)
				return NULL;
			else
			{
	jal_parser_trace0(  " jal_parser_direct_declarator 5 ");

				inner
					= build_function_declarator (args,
					build_id_declarator (NULL_TREE));
				return jal_parser_direct_declarator_inner (parser, *seen_id,
					inner);
			}
		}

	jal_parser_trace0(  " jal_parser_direct_declarator 6 ");

		/* A parenthesized declarator.  */
		inner = jal_parser_declarator (parser, type_seen_p, kind, seen_id);
		if (inner != NULL && attrs != NULL)
			inner = build_attrs_declarator (attrs, inner);
		if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
		{
			jal_parser_consume_token (parser);
			if (inner == NULL)
				return NULL;
			else
				return jal_parser_direct_declarator_inner (parser, *seen_id, inner);
		}
		else
		{
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
				"9 expected %<)%>");
			return NULL;
		}
	}
	else
	{
		if (kind == C_DTR_NORMAL)
		{
			jal_parser_error (parser, "expected identifier or %<(%>");
			return NULL;
		}
		else
			return build_id_declarator (NULL_TREE);
	}
}



/* Parse part of a direct declarator or direct abstract declarator,
given that some (in INNER) has already been parsed; ID_PRESENT is
true if an identifier is present, false for an abstract
declarator.  */

static struct jal_declarator *
jal_parser_direct_declarator_inner (jal_parser *parser, bool id_present,
struct jal_declarator *inner)
{
	/* Parse a sequence of array declarators and parameter lists.  */
	if (jal_parser_next_token_is (parser, CPP_OPEN_SQUARE))
	{
		struct jal_declarator *declarator;
		struct jal_declspecs *quals_attrs = build_null_declspecs ();
		bool static_seen;
		bool star_seen;
		tree dimen;
		jal_parser_consume_token (parser);
		jal_parser_trace0(  "jal_parser_declspecs C3" );

		jal_parser_declspecs (parser, quals_attrs, false, false, true);
		static_seen = jal_parser_next_token_is_keyword (parser, RID_STATIC);
		if (static_seen)
			jal_parser_consume_token (parser);
		if (static_seen && !quals_attrs->declspecs_seen_p)
			jal_parser_trace0(  "jal_parser_declspecs C4" );

		jal_parser_declspecs (parser, quals_attrs, false, false, true);
		if (!quals_attrs->declspecs_seen_p)
			quals_attrs = NULL;
		/* If "static" is present, there must be an array dimension.
		Otherwise, there may be a dimension, "*", or no
		dimension.  */
		if (static_seen)
		{
			star_seen = false;
			jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM C" );

			dimen = jal_parser_expr_no_commas (parser, NULL).value;
		}
		else
		{
			if (jal_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
			{
				dimen = NULL_TREE;
				star_seen = false;
			}
			else if (jal_parser_next_token_is (parser, CPP_MULT))
			{
				jal_parser_trace0(  "jal_parser_direct_declarator_inner CPP MULT " );

				if (jal_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
				{
					dimen = NULL_TREE;
					star_seen = true;
					jal_parser_consume_token (parser);
				}
				else
				{
					star_seen = false;
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM D" );
					dimen = jal_parser_expr_no_commas (parser, NULL).value;
				}
			}
			else
			{
				star_seen = false;
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM E" );

				dimen = jal_parser_expr_no_commas (parser, NULL).value;
			}
		}
		if (jal_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
			jal_parser_consume_token (parser);
		else
		{
			jal_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
				"expected %<]%>");
			return NULL;
		}
		declarator = build_array_declarator (dimen, quals_attrs, static_seen,
			star_seen);
		if (declarator == NULL)
			return NULL;
		inner = set_array_declarator_inner (declarator, inner);
		return jal_parser_direct_declarator_inner (parser, id_present, inner);
	}
	else if (jal_parser_next_token_is (parser, CPP_OPEN_PAREN))
	{
		tree attrs;
		struct jal_arg_info *args;
		jal_parser_consume_token (parser);

		attrs = jal_parser_attributes (parser);
		args = jal_parser_parms_declarator (parser, id_present, attrs);
		if (args == NULL)
			return NULL;
		else
		{
			inner = build_function_declarator (args, inner);
			return jal_parser_direct_declarator_inner (parser, id_present, inner);
		}
	}
	return inner;
}

/* Parse a parameter list or identifier list, including the closing
parenthesis but not the opening one.  ATTRS are the attributes at
the start of the list.  ID_LIST_OK is true if an identifier list is
acceptable; such a list must not have attributes at the start.  */

static struct jal_arg_info *
jal_parser_parms_declarator (jal_parser *parser, bool id_list_ok, tree attrs)
{
	push_scope ();
	declare_parm_level ();

		jal_parser_trace0(  "jal_parser_parms_declarator" );

	/* If the list starts with an identifier, it is an identifier list.
	Otherwise, it is either a prototype list or an empty list.  */
	if (id_list_ok
		&& !attrs
		&& jal_parser_next_token_is (parser, CPP_NAME)
		&& jal_parser_peek_token (parser)->id_kind == C_ID_ID)
	{
		tree list = NULL_TREE, *nextp = &list;
		while (jal_parser_next_token_is (parser, CPP_NAME)
			&& jal_parser_peek_token (parser)->id_kind == C_ID_ID)
		{
			*nextp = build_tree_list (NULL_TREE,
				jal_parser_peek_token (parser)->value);
			nextp = & TREE_CHAIN (*nextp);
			jal_parser_consume_token (parser);
			if (jal_parser_next_token_is_not (parser, CPP_COMMA))
				break;
			jal_parser_consume_token (parser);
			if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
			{
				jal_parser_error (parser, "expected identifier");
				break;
			}
		}
		if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
		{
			struct jal_arg_info *ret = XOBNEW (&parser_obstack, struct jal_arg_info);
			ret->parms = 0;
			ret->tags = 0;
			ret->types = list;
			ret->others = 0;
			ret->pending_sizes = 0;
			ret->had_vla_unspec = 0;
			jal_parser_consume_token (parser);
			pop_scope ();
			return ret;
		}
		else
		{
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
				"10 expected %<)%>");
			pop_scope ();
			return NULL;
		}
	}
	else
	{
		struct jal_arg_info *ret = jal_parser_parms_list_declarator (parser, attrs);
		pop_scope ();
		return ret;
	}
}

/* Parse a parameter list (possibly empty), including the closing
parenthesis but not the opening one.  ATTRS are the attributes at
the start of the list.  */

static struct jal_arg_info *
jal_parser_parms_list_declarator (jal_parser *parser, tree attrs)
{
	bool good_parm = false;

	jal_parser_trace0(  "jal_parser_parms_list_declarator 1" );

	if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
	{
		struct jal_arg_info *ret = XOBNEW (&parser_obstack, struct jal_arg_info);
		ret->parms = 0;
		ret->tags = 0;
		ret->types = 0;
		ret->others = 0;
		ret->pending_sizes = 0;
		ret->had_vla_unspec = 0;
		jal_parser_consume_token (parser);
		return ret;
	}
	// AF TODO REMOVE
	//if (jal_parser_next_token_is (parser, CPP_ELLIPSIS))
	//{
	//	struct jal_arg_info *ret = XOBNEW (&parser_obstack, struct jal_arg_info);
	//	ret->parms = 0;
	//	ret->tags = 0;
	//	ret->others = 0;
	//	ret->pending_sizes = 0;
	//	ret->had_vla_unspec = 0;
	//	/* Suppress -Wold-style-definition for this case.  */
	//	ret->types = error_mark_node;
	//	error ("%HISO C requires a named argument before %<...%>",
	//		&jal_parser_peek_token (parser)->location);
	//	jal_parser_consume_token (parser);
	//	if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
	//	{
	//		jal_parser_consume_token (parser);
	//		return ret;
	//	}
	//	else
	//	{
	//		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
	//			"expected %<)%>");
	//		return NULL;
	//	}
	//}
	/* Nonempty list of parameters, either terminated with semicolon
	(forward declarations; recurse) or with close parenthesis (normal
	function) or with ", ... )" (variadic function).  */
	while (true)
	{
		/* Parse a parameter.  */
		struct jal_parm *parm = jal_parser_parameter_declaration (parser, attrs);
		attrs = NULL_TREE;
		if (parm != NULL)
		{
			good_parm = true;
			push_parm_decl (parm);
		}

		// AF TODO REMOVE
		//if (jal_parser_next_token_is (parser, CPP_SEMICOLON))
		//{
		//	tree new_attrs;
		//	jal_parser_consume_token (parser);
		//	mark_forward_parm_decls ();
		//	new_attrs = jal_parser_attributes (parser);
		//	return jal_parser_parms_list_declarator (parser, new_attrs);
		//}
		if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
		{
			jal_parser_consume_token (parser);
			if (good_parm)
				return get_parm_info (false);
			else
			{
				struct jal_arg_info *ret
					= XOBNEW (&parser_obstack, struct jal_arg_info);
				ret->parms = 0;
				ret->tags = 0;
				ret->types = 0;
				ret->others = 0;
				ret->pending_sizes = 0;
				ret->had_vla_unspec = 0;
				return ret;
			}
		}
		if (!jal_parser_require (parser, CPP_COMMA,
			"expected %<,%> or %<)%>"))
		{
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
			return NULL;
		}

		//if (jal_parser_next_token_is (parser, CPP_ELLIPSIS))
		//{
		//	jal_parser_consume_token (parser);
		//	if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
		//	{
		//		jal_parser_consume_token (parser);
		//		if (good_parm)
		//			return get_parm_info (true);
		//		else
		//		{
		//			struct jal_arg_info *ret
		//				= XOBNEW (&parser_obstack, struct jal_arg_info);
		//			ret->parms = 0;
		//			ret->tags = 0;
		//			ret->types = 0;
		//			ret->others = 0;
		//			ret->pending_sizes = 0;
		//			ret->had_vla_unspec = 0;
		//			return ret;
		//		}
		//	}
		//	else
		//	{
		//		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
		//			"expected %<)%>");
		//		return NULL;
		//	}
		//}
	}
}


/* Parse a parameter declaration.  ATTRS are the attributes at the
start of the declaration if it is the first parameter.  */

static struct jal_parm *
jal_parser_parameter_declaration (jal_parser *parser, tree attrs)
{
	struct jal_declspecs *specs;
	struct jal_declarator *declarator;
	tree prefix_attrs;
	tree postfix_attrs = NULL_TREE;
	bool dummy = false;
	bool isOut = false;

	jal_parser_trace0(  "jal_parser_parameter_declaration 1");

	specs = build_null_declspecs ();
	jal_parser_parse_var_type(parser, specs, true);

	jal_parser_trace0(  "jal_parser_parameter_declaration 2");

	if (parser->error)
	{
		jal_parser_skip_to_end_of_block_or_statement (parser);
		return NULL;
	}

	// AF REQUIRED ?????
	if (attrs)
	{
		jal_parser_trace0(  "TRACE: jal_parser_parameter_declaration 3");

		declspecs_add_attrs (specs, attrs);
		attrs = NULL_TREE;
	}


	//jal_parser_trace0(  "TRACE: jal_parser_parameter_declaration 4");
	// jal_parser_declspecs (parser, specs, true, true, true);
	finish_declspecs (specs);


	pending_xref_error ();
	prefix_attrs = specs->attrs;
	specs->attrs = NULL_TREE;
	//declarator = jal_parser_declarator (parser, specs->type_seen_p,
	//	C_DTR_PARM, &dummy);

	// expect in, out, or in out
	if ( jal_parser_next_token_is_keyword ( parser, RID_IN ) )
	{
		jal_parser_consume_token (parser);
		if ( jal_parser_next_token_is_keyword ( parser, RID_OUT ) )
		{
			isOut = true;
			jal_parser_consume_token (parser);
			jal_parser_trace0(  "jal_parser_parameter_declaration IN OUT parameter");
		}
		else
		{
			jal_parser_trace0(  "jal_parser_parameter_declaration IN parameter");
		}
	}
	else if ( jal_parser_next_token_is_keyword ( parser, RID_OUT ) )
	{
		isOut = true;
		jal_parser_consume_token (parser);
		jal_parser_trace0(  "jal_parser_parameter_declaration OUT parameter");
	}
	else
	{
		jal_parser_error (parser, "expected in, out or in out specifier");		
	}


	declarator = jal_parser_direct_declarator (parser, specs->type_seen_p, C_DTR_NORMAL, &dummy);


	if (declarator == NULL)
	{
		jal_parser_trace0(  "TRACE: jal_parser_parameter_declaration 5");

		jal_parser_skip_until_found (parser, CPP_COMMA, NULL);
		return NULL;
	}

	if ( isOut )
	{
		struct jal_declspecs *quals_attrs = build_null_declspecs ();
		jal_parser_trace0(  "jal_parser_parameter_declaration  convert to pointer" );
		declarator = make_pointer_declarator (quals_attrs, declarator);
	}

	if (jal_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
		postfix_attrs = jal_parser_attributes (parser);
	return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
		declarator);
}

/* Parse a string literal in an asm expression.  It should not be
translated, and wide string literals are an error although
permitted by the syntax.  This is a GNU extension.

asm-string-literal:
string-literal

??? At present, following the old parser, the caller needs to have
set lex_untranslated_string to 1.  It would be better to follow the
C++ parser rather than using this kludge.  */

static tree
jal_parser_asm_string_literal (jal_parser *parser)
{
	tree str;
	if (jal_parser_next_token_is (parser, CPP_STRING))
	{
		str = jal_parser_peek_token (parser)->value;
		jal_parser_consume_token (parser);
	}
	else
	{
		jal_parser_error (parser, "expected string literal");
		str = NULL_TREE;
	}
	return str;
}

/* Parse a simple asm expression.  This is used in restricted
contexts, where a full expression with inputs and outputs does not
make sense.  This is a GNU extension.

simple-asm-expr:
asm ( asm-string-literal )
*/

static tree
jal_parser_simple_asm_expr (jal_parser *parser)
{
	tree str;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_ASM));
	/* ??? Follow the C++ parser rather than using the
	lex_untranslated_string kludge.  */
	parser->lex_untranslated_string = true;
	jal_parser_consume_token (parser);
	if (!jal_parser_require (parser, CPP_OPEN_PAREN, "6 expected %<(%>"))
	{
		parser->lex_untranslated_string = false;
		return NULL_TREE;
	}
	str = jal_parser_asm_string_literal (parser);
	parser->lex_untranslated_string = false;
	if (!jal_parser_require (parser, CPP_CLOSE_PAREN, "11 expected %<)%>"))
	{
		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
		return NULL_TREE;
	}
	return str;
}

/* Parse (possibly empty) attributes.  This is a GNU extension.

attributes:
empty
attributes attribute

attribute:
__attribute__ ( ( attribute-list ) )

attribute-list:
attrib
attribute_list , attrib

attrib:
empty
any-word
any-word ( identifier )
any-word ( identifier , nonempty-expr-list )
any-word ( expr-list )

where the "identifier" must not be declared as a type, and
"any-word" may be any identifier (including one declared as a
type), a reserved word storage class specifier, type specifier or
type qualifier.  ??? This still leaves out most reserved keywords
(following the old parser), shouldn't we include them, and why not
allow identifiers declared as types to start the arguments?  */

static tree
jal_parser_attributes (jal_parser *parser)
{
	tree attrs = NULL_TREE;


	jal_parser_trace0(  "TRACE: jal_parser_attributes 1");

	while (jal_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
	{
		/* ??? Follow the C++ parser rather than using the
		lex_untranslated_string kludge.  */
		parser->lex_untranslated_string = true;
		jal_parser_consume_token (parser);
		if (!jal_parser_require (parser, CPP_OPEN_PAREN, "7 expected %<(%>"))
		{
			parser->lex_untranslated_string = false;
			return attrs;
		}
		if (!jal_parser_require (parser, CPP_OPEN_PAREN, "8 expected %<(%>"))
		{
			parser->lex_untranslated_string = false;
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
			return attrs;
		}
		/* Parse the attribute list.  */
		while (jal_parser_next_token_is (parser, CPP_COMMA)
			|| jal_parser_next_token_is (parser, CPP_NAME)
			|| jal_parser_next_token_is (parser, CPP_KEYWORD))
		{
			tree attr, attr_name, attr_args;
			if (jal_parser_next_token_is (parser, CPP_COMMA))
			{
				jal_parser_consume_token (parser);
				continue;
			}
			if (jal_parser_next_token_is (parser, CPP_KEYWORD))
			{
				/* ??? See comment above about what keywords are
				accepted here.  */
				bool ok;
				switch (jal_parser_peek_token (parser)->keyword)
				{
				case RID_STATIC:
				case RID_UNSIGNED:
				case RID_LONG:
				//case RID_CONST:
				case RID_EXTERN:
				case RID_REGISTER:
				case RID_TYPEDEF:
				case RID_SHORT:
				case RID_INLINE:
				case RID_VOLATILE:
				case RID_SIGNED:
				case RID_AUTO:
				case RID_RESTRICT:
				case RID_THREAD:
				case RID_INT:
				case RID_CHAR:
				case RID_FLOAT:
				case RID_DOUBLE:
				case RID_VOID:
				case RID_DFLOAT32:
				case RID_DFLOAT64:
				case RID_DFLOAT128:
				case RID_FRACT:
				case RID_ACCUM:
				case RID_SAT:
					ok = true;
					break;
				default:
					ok = false;
					break;
				}
				if (!ok)
					break;
			}
			attr_name = jal_parser_peek_token (parser)->value;
			jal_parser_consume_token (parser);
			if (jal_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
			{
				attr = build_tree_list (attr_name, NULL_TREE);
				attrs = chainon (attrs, attr);
				continue;
			}
			jal_parser_consume_token (parser);
			/* Parse the attribute contents.  If they start with an
			identifier which is followed by a comma or close
			parenthesis, then the arguments start with that
			identifier; otherwise they are an expression list.  */
			if (jal_parser_next_token_is (parser, CPP_NAME)
				&& jal_parser_peek_token (parser)->id_kind == C_ID_ID
				&& ((jal_parser_peek_2nd_token (parser)->type == CPP_COMMA)
				|| (jal_parser_peek_2nd_token (parser)->type
				== CPP_CLOSE_PAREN)))
			{
				tree arg1 = jal_parser_peek_token (parser)->value;
				jal_parser_consume_token (parser);
				if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
					attr_args = build_tree_list (NULL_TREE, arg1);
				else
				{
					jal_parser_consume_token (parser);
	
					jal_parser_trace0(  "CALL jal_parser_expr_list FROM A" );

					attr_args = tree_cons (NULL_TREE, arg1,
						jal_parser_expr_list (parser, false));
				}
			}
			else
			{
				if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
					attr_args = NULL_TREE;
				else
				{
					jal_parser_trace0(  "CALL jal_parser_expr_list FROM B" );

					attr_args = jal_parser_expr_list (parser, false);
				}
			}
			attr = build_tree_list (attr_name, attr_args);
			if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
				jal_parser_consume_token (parser);
			else
			{
				parser->lex_untranslated_string = false;
				jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
					"12 expected %<)%>");
				return attrs;
			}
			attrs = chainon (attrs, attr);
		}
		if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
			jal_parser_consume_token (parser);
		else
		{
			parser->lex_untranslated_string = false;
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
				"13 expected %<)%>");
			return attrs;
		}
		if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
			jal_parser_consume_token (parser);
		else
		{
			parser->lex_untranslated_string = false;
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
				"14 expected %<)%>");
			return attrs;
		}
		parser->lex_untranslated_string = false;
	}
	return attrs;
}

/* Parse a type name (C90 6.5.5, C99 6.7.6).

type-name:
specifier-qualifier-list abstract-declarator[opt]
*/

static struct jal_type_name *
jal_parser_type_name (jal_parser *parser)
{
	struct jal_declspecs *specs = build_null_declspecs ();
	struct jal_declarator *declarator;
	struct jal_type_name *ret;
	bool dummy = false;

	jal_parser_trace0(  "jal_parser_type_name ENTRY" );

	jal_parser_declspecs (parser, specs, false, true, true);

	jal_parser_trace0(  "jal_parser_type_name got DELCSPEC" );

	if (!specs->declspecs_seen_p)
	{
		jal_parser_error (parser, "expected specifier-qualifier-list");
		jal_parser_trace0(  "jal_parser_type_name EXIT return NULL" );
		return NULL;
	}
	pending_xref_error ();
	finish_declspecs (specs);

	jal_parser_trace0(  "jal_parser_type_name get DECLARATOR" );

	declarator = jal_parser_declarator (parser, specs->type_seen_p,
		C_DTR_ABSTRACT, &dummy);

	jal_parser_trace0(  "jal_parser_type_name got DECLARATOR" );

	if (declarator == NULL)
	{
		jal_parser_trace0(  "jal_parser_type_name EXIT return NULL" );
		return NULL;
	}
	ret = XOBNEW (&parser_obstack, struct jal_type_name);
	ret->specs = specs;
	ret->declarator = declarator;
	
	jal_parser_trace0(  "jal_parser_type_name EXIT return type" );

	return ret;
}

/* Parse an initializer (C90 6.5.7, C99 6.7.8).

initializer:
assignment-expression
{ initializer-list }
{ initializer-list , }

initializer-list:
designation[opt] initializer
initializer-list , designation[opt] initializer

designation:
designator-list =

designator-list:
designator
designator-list designator

designator:
array-designator
. identifier

array-designator:
[ constant-expression ]

GNU extensions:

initializer:
{ }

designation:
array-designator
identifier :

array-designator:
[ constant-expression ... constant-expression ]

Any expression without commas is accepted in the syntax for the
constant-expressions, with non-constant expressions rejected later.

This function is only used for top-level initializers; for nested
ones, see jal_parser_initval.  */

static struct jal_expr
jal_parser_initializer (jal_parser *parser)
{
	if (jal_parser_next_token_is (parser, CPP_OPEN_BRACE))
		return jal_parser_braced_init (parser, NULL_TREE, false);
	else
	{
		struct jal_expr ret;
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM F" );

		ret = jal_parser_expr_no_commas (parser, NULL);
		if (TREE_CODE (ret.value) != STRING_CST
			&& TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
			ret = default_function_array_conversion (ret);
		return ret;
	}
}

/* Parse a braced initializer list.  TYPE is the type specified for a
compound literal, and NULL_TREE for other initializers and for
nested braced lists.  NESTED_P is true for nested braced lists,
false for the list of a compound literal or the list that is the
top-level initializer in a declaration.  */

static struct jal_expr
jal_parser_braced_init (jal_parser *parser, tree type, bool nested_p)
{
	// location_t brace_loc = jal_parser_peek_token (parser)->location;
	gcc_assert (jal_parser_next_token_is (parser, CPP_OPEN_BRACE));
	jal_parser_consume_token (parser);
	if (nested_p)
		push_init_level (0);
	else
		really_start_incremental_init (type);
	if (jal_parser_next_token_is (parser, CPP_CLOSE_BRACE))
	{
		//if (pedantic)
		//	pedwarn ("%HISO C forbids empty initializer braces", &brace_loc);
	}
	else
	{
		/* Parse a non-empty initializer list, possibly with a trailing
		comma.  */
		while (true)
		{
			jal_parser_initelt (parser);
			if (parser->error)
				break;
			if (jal_parser_next_token_is (parser, CPP_COMMA))
				jal_parser_consume_token (parser);
			else
				break;
			if (jal_parser_next_token_is (parser, CPP_CLOSE_BRACE))
				break;
		}
	}
	if (jal_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
	{
		struct jal_expr ret;
		ret.value = error_mark_node;
		ret.original_code = ERROR_MARK;
		jal_parser_skip_until_found (parser, CPP_CLOSE_BRACE, "expected %<}%>");
		return ret;
	}
	jal_parser_consume_token (parser);
	return pop_init_level (0);
}

/* Parse a nested initializer, including designators.  */

static void
jal_parser_initelt (jal_parser *parser)
{
	/* Parse any designator or designator list.  A single array
	designator may have the subsequent "=" omitted in GNU C, but a
	longer list or a structure member designator may not.  */
	if (jal_parser_next_token_is (parser, CPP_NAME)
		&& jal_parser_peek_2nd_token (parser)->type == CPP_COLON)
	{
		/* Old-style structure member designator.  */
		set_init_label (jal_parser_peek_token (parser)->value);
		//if (pedantic)
		//{
		//	/* Use the colon as the error location.  */
		//	pedwarn ("%Hobsolete use of designated initializer with %<:%>",
		//		&jal_parser_peek_2nd_token (parser)->location);
		//}
		jal_parser_consume_token (parser);
		jal_parser_consume_token (parser);
	}
	else
	{
		/* des_seen is 0 if there have been no designators, 1 if there
		has been a single array designator and 2 otherwise.  */
		int des_seen = 0;
		/* Location of a designator.  */
		location_t des_loc;
		while (jal_parser_next_token_is (parser, CPP_OPEN_SQUARE)
			|| jal_parser_next_token_is (parser, CPP_DOT))
		{
			int des_prev = des_seen;
			if (!des_seen)
				des_loc = jal_parser_peek_token (parser)->location;
			if (des_seen < 2)
				des_seen++;
			if (jal_parser_next_token_is (parser, CPP_DOT))
			{
				des_seen = 2;
				jal_parser_consume_token (parser);
				if (jal_parser_next_token_is (parser, CPP_NAME))
				{
					set_init_label (jal_parser_peek_token (parser)->value);
					jal_parser_consume_token (parser);
				}
				else
				{
					struct jal_expr init;
					init.value = error_mark_node;
					init.original_code = ERROR_MARK;
					jal_parser_error (parser, "expected identifier");
					jal_parser_skip_until_found (parser, CPP_COMMA, NULL);
					process_init_element (init,false);
					return;
				}
			}
			else
			{
				tree first, second;
				location_t ellipsis_loc;
				/* ??? Following the old parser, [ objc-receiver
				objc-message-args ] is accepted as an initializer,
				being distinguished from a designator by what follows
				the first assignment expression inside the square
				brackets, but after a first array designator a
				subsequent square bracket is for Objective-C taken to
				start an expression, using the obsolete form of
				designated initializer without '=', rather than
				possibly being a second level of designation: in LALR
				terms, the '[' is shifted rather than reducing
				designator to designator-list.  */
				if (des_prev == 1 && c_dialect_objc ())
				{
					des_seen = des_prev;
					break;
				}
				if (des_prev == 0 && c_dialect_objc ())
				{
					/* This might be an array designator or an
					Objective-C message expression.  If the former,
					continue parsing here; if the latter, parse the
					remainder of the initializer given the starting
					primary-expression.  ??? It might make sense to
					distinguish when des_prev == 1 as well; see
					previous comment.  */
					tree rec, args;
					struct jal_expr mexpr;
					jal_parser_consume_token (parser);
					if (jal_parser_peek_token (parser)->type == CPP_NAME
						&& ((jal_parser_peek_token (parser)->id_kind
						== C_ID_TYPENAME)
						|| (jal_parser_peek_token (parser)->id_kind
						== C_ID_CLASSNAME)))
					{
						/* Type name receiver.  */
						tree id = jal_parser_peek_token (parser)->value;
						jal_parser_consume_token (parser);
						rec = objc_get_class_reference (id);
						goto parse_message_args;
					}
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM G" );

					first = jal_parser_expr_no_commas (parser, NULL).value;
					if (jal_parser_next_token_is (parser, CPP_ELLIPSIS)
						|| jal_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
						goto array_desig_after_first;
					/* Expression receiver.  So far only one part
					without commas has been parsed; there might be
					more of the expression.  */
					rec = first;
					while (jal_parser_next_token_is (parser, CPP_COMMA))
					{
						struct jal_expr next;
						jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM H" );

						next = jal_parser_expr_no_commas (parser, NULL);
						next = default_function_array_conversion (next);
						rec = build_compound_expr (rec, next.value);
					}
parse_message_args:
					/* Now parse the objc-message-args.  */
					// args = jal_parser_objc_message_args (parser);
					jal_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
						"expected %<]%>");
					mexpr.value
						= objc_build_message_expr (build_tree_list (rec, args));
					mexpr.original_code = ERROR_MARK;
					/* Now parse and process the remainder of the
					initializer, starting with this message
					expression as a primary-expression.  */
					jal_parser_initval (parser, &mexpr);
					return;
				}
				jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM K" );

				first = jal_parser_expr_no_commas (parser, NULL).value;
array_desig_after_first:
				if (jal_parser_next_token_is (parser, CPP_ELLIPSIS))
				{
					ellipsis_loc = jal_parser_peek_token (parser)->location;
					jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM L" );

					second = jal_parser_expr_no_commas (parser, NULL).value;
				}
				else
					second = NULL_TREE;
				if (jal_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
				{
					jal_parser_consume_token (parser);
					set_init_index (first, second);
					//if (pedantic && second)
					//	pedwarn ("%HISO C forbids specifying range of "
					//	"elements to initialize", &ellipsis_loc);
				}
				else
					jal_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
					"expected %<]%>");
			}
		}
		if (des_seen >= 1)
		{
			if (jal_parser_next_token_is (parser, CPP_EQ))
			{
				//if (pedantic && !flag_isoc99)
				//	pedwarn ("%HISO C90 forbids specifying subobject "
				//	"to initialize", &des_loc);
				jal_parser_consume_token (parser);
			}
			else
			{
				if (des_seen == 1)
				{
					//if (pedantic)
					//	pedwarn ("%Hobsolete use of designated initializer "
					//	"without %<=%>",
					//	&jal_parser_peek_token (parser)->location);
				}
				else
				{
					struct jal_expr init;
					init.value = error_mark_node;
					init.original_code = ERROR_MARK;
					jal_parser_error (parser, "expected %<=%>");
					jal_parser_skip_until_found (parser, CPP_COMMA, NULL);
					process_init_element (init, false);
					return;
				}
			}
		}
	}
	jal_parser_initval (parser, NULL);
}

/* Parse a nested initializer; as jal_parser_initializer but parses
initializers within braced lists, after any designators have been
applied.  If AFTER is not NULL then it is an Objective-C message
expression which is the primary-expression starting the
initializer.  */

static void
jal_parser_initval (jal_parser *parser, struct jal_expr *after)
{
	struct jal_expr init;
	gcc_assert (!after || c_dialect_objc ());
	if (jal_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
		init = jal_parser_braced_init (parser, NULL_TREE, true);
	else
	{
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM M" );

		init = jal_parser_expr_no_commas (parser, after);
		if (init.value != NULL_TREE
			&& TREE_CODE (init.value) != STRING_CST
			&& TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
			init = default_function_array_conversion (init);
	}
	process_init_element (init, false);
}

/* Parse a compound statement (possibly a function body) (C90 6.6.2,
C99 6.8.2).

compound-statement:
{ block-item-list[opt] }
{ label-declarations block-item-list }

block-item-list:
block-item
block-item-list block-item

block-item:
nested-declaration
statement

nested-declaration:
declaration

GNU extensions:

compound-statement:
{ label-declarations block-item-list }

nested-declaration:
__extension__ nested-declaration
nested-function-definition

label-declarations:
label-declaration
label-declarations label-declaration

label-declaration:
__label__ identifier-list ;

Allowing the mixing of declarations and code is new in C99.  The
GNU syntax also permits (not shown above) labels at the end of
compound statements, which yield an error.  We don't allow labels
on declarations; this might seem like a natural extension, but
there would be a conflict between attributes on the label and
prefix attributes on the declaration.  ??? The syntax follows the
old parser in requiring something after label declarations.
Although they are erroneous if the labels declared aren't defined,
is it useful for the syntax to be this way?

OpenMP:

block-item:
openmp-directive

openmp-directive:
barrier-directive
flush-directive  */

static tree jal_parser_compound_statement (jal_parser *parser)
{
	tree stmt;

	jal_parser_trace0(  "jal_parser_compound_statement 1" );

	// if (!jal_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
	//   return error_mark_node;
	stmt = jal_begin_compound_stmt (true);
	jal_parser_compound_statement_nostart (parser);

	jal_parser_trace0(  "jal_parser_compound_statement 2" );

	return c_end_compound_stmt (stmt, true);
}




/* Parse a compound statement except for the opening brace.  This is
used for parsing both compound statements and statement expressions
(which follow different paths to handling the opening).  */

static void jal_parser_compound_statement_nostart (jal_parser *parser)
{
	bool last_stmt = false;
	bool last_label = false;
	location_t label_loc;

	jal_parser_trace0(  "jal_parser_compound_statement_nostart 1" );

	// stop when reaching RID_END
	// if (jal_parser_next_token_is (parser, CPP_CLOSE_BRACE))
	if (jal_parser_next_token_is_keyword (parser, RID_END))
	{
		jal_parser_trace0(  "jal_parser_compound_statement_nostart 2" );
		jal_parser_consume_token (parser);
		return;
	}

	jal_parser_trace0(  "jal_parser_compound_statement_nostart 3" );

	if (jal_parser_next_token_is_keyword (parser, RID_LABEL))
	{
		//location_t err_loc = jal_parser_peek_token (parser)->location;

		jal_parser_trace0(  "jal_parser_compound_statement_nostart 4" );

		/* Read zero or more forward-declarations for labels that nested
		functions can jump to.  */
		while (jal_parser_next_token_is_keyword (parser, RID_LABEL))
		{
			jal_parser_consume_token (parser);
			/* Any identifiers, including those declared as type names,
			are OK here.  */
			while (true)
			{
				tree label;
				if (jal_parser_next_token_is_not (parser, CPP_NAME))
				{
					jal_parser_error (parser, "expected identifier");
					break;
				}
				label
					= declare_label (jal_parser_peek_token (parser)->value);
				C_DECLARED_LABEL_FLAG (label) = 1;
				add_stmt (build_stmt (DECL_EXPR, label));
				jal_parser_consume_token (parser);
				if (jal_parser_next_token_is (parser, CPP_COMMA))
					jal_parser_consume_token (parser);
				else
					break;
			}
			jal_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
		}
		//if (pedantic)
		//	pedwarn ("%HISO C forbids label declarations", &err_loc);
	}
	/* We must now have at least one statement, label or declaration.  */
	//if (jal_parser_next_token_is (parser, CPP_CLOSE_BRACE))
	//  {
	//    jal_parser_error (parser, "expected declaration or statement");
	//    jal_parser_consume_token (parser);
	//    return;
	//  }
	while (!jal_parser_next_token_is_keyword (parser, RID_END))
	{

		location_t loc = jal_parser_peek_token (parser)->location;
		jal_parser_trace0(  "jal_parser_compound_statement_nostart 5" );

		if ( jal_parser_peek_2nd_token (parser)->type == CPP_COLON ) 
			// jal_parser_next_token_is_keyword (parser, RID_OTHERWISE)
			// || (jal_parser_next_token_is (parser, CPP_NAME)
			// && jal_parser_peek_2nd_token (parser)->type == CPP_COLON))
		{
			jal_parser_trace0(  "jal_parser_compound_statement_nostart 5a" );
			label_loc = jal_parser_peek_token (parser)->location;
			last_label = true;
			last_stmt = false;
			jal_parser_label (parser);
		}
		else if (jal_parser_next_token_is (parser, CPP_EOF))
		{
			jal_parser_error (parser, "expected declaration or statement");
			return;
		}
		else if (jal_parser_next_token_is_keyword (parser, RID_ELSE))
		{
			// don't consume token
			if (parser->in_if_block) 
			{
				// error ("%H""expected %<}%> before %<else%>", &loc);
				jal_parser_trace0(  "ELSE BLOCK IN IF " );
				return;
			}
			else 
			{
				error ("%H%<else%> without a previous %<if%>", &loc);
				jal_parser_consume_token (parser);
				continue;
			}
		}
		else if (jal_parser_next_token_is_keyword (parser, RID_ELSIF))
		{
			// don't consume token
			if (parser->in_if_block) 
			{
				// error ("%H""expected %<}%> before %<else%>", &loc);
				jal_parser_trace0(  "ELSIF BLOCK IN IF " );

				return;
			}
			else 
			{
				error ("%H%<elsif%> without a previous %<if%>", &loc);
				jal_parser_consume_token (parser);
				continue;
			}
		}
		else
		{
//statement:
			last_label = false;
			last_stmt = true;
			jal_parser_trace0(  "jal_parser_compound_statement_nostart 6" );
			jal_parser_statement_after_labels (parser);
		}

		parser->error = false;
	}
	jal_parser_trace0(  "jal_parser_compound_statement_nostart 7 (END)" );

	if (last_label)
		error ("%Hlabel at end of compound statement", &label_loc);
	jal_parser_consume_token (parser);
	jal_parser_trace0(  "jal_parser_compound_statement_nostart EXIT" );
}



/* Parse a label (C90 6.6.1, C99 6.8.1).

label:
identifier : attributes[opt]
case constant-expression :
default :

GNU extensions:

label:
case constant-expression ... constant-expression :

The use of attributes on labels is a GNU extension.  The syntax in
GNU C accepts any expressions without commas, non-constant
expressions being rejected later.  */

static void
jal_parser_label (jal_parser *parser)
{
	location_t loc1 = jal_parser_peek_token (parser)->location;
	tree label = NULL_TREE;

	jal_parser_trace0(  "jal_parser_label 1" );

	if (!jal_parser_next_token_is_keyword (parser, RID_OTHERWISE))
	{
		tree exp1, exp2;
		jal_parser_trace0(  "jal_parser_label 2" );
		jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM N" );

		exp1 = jal_parser_expr_no_commas (parser, NULL).value;
		if (jal_parser_next_token_is (parser, CPP_COLON))
		{
			jal_parser_trace0(  "jal_parser_label 3" );

			jal_parser_consume_token (parser);
			label = do_case (exp1, NULL_TREE);
		}
		else if (jal_parser_next_token_is (parser, CPP_ELLIPSIS))
		{
			jal_parser_trace0(  "jal_parser_label 4" );

			jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM O" );

			exp2 = jal_parser_expr_no_commas (parser, NULL).value;
			if (jal_parser_require (parser, CPP_COLON, "expected %<:%>"))
				label = do_case (exp1, exp2);
		}
		else
		{
			jal_parser_trace0(  "jal_parser_label 5" );

			jal_parser_error (parser, "expected %<:%> or %<...%>");
		}
	}
	else if (jal_parser_next_token_is_keyword (parser, RID_OTHERWISE))
	{
		jal_parser_trace0(  "jal_parser_label 6" );

		jal_parser_consume_token (parser);
		if (jal_parser_require (parser, CPP_COLON, "expected %<:%>"))
			label = do_case (NULL_TREE, NULL_TREE);
	}
	else
	{
		tree name = jal_parser_peek_token (parser)->value;
		tree tlab;
		tree attrs;
		location_t loc2 = jal_parser_peek_token (parser)->location;

		jal_parser_trace0(  "jal_parser_label 7" );

		gcc_assert (jal_parser_next_token_is (parser, CPP_NAME));
		jal_parser_consume_token (parser);
		gcc_assert (jal_parser_next_token_is (parser, CPP_COLON));
		jal_parser_consume_token (parser);
		attrs = jal_parser_attributes (parser);
		tlab = define_label (loc2, name);
		if (tlab)
		{
			decl_attributes (&tlab, attrs, 0);
			label = add_stmt (build_stmt (LABEL_EXPR, tlab));
		}
	}


	if (label)
	{
		SET_EXPR_LOCATION (label, loc1);

		jal_parser_trace0(  "jal_parser_label 8" );

		if (jal_parser_next_token_starts_declspecs (parser)
			&& !(jal_parser_next_token_is (parser, CPP_NAME)
			&& jal_parser_peek_2nd_token (parser)->type == CPP_COLON))
		{
			error ("%Ha label can only be part of a statement and "
				"a declaration is not a statement",
				&jal_parser_peek_token (parser)->location);
	jal_parser_trace0(  "CALL FROM D" );

		jal_parser_procedure_or_function (	parser, true, false );
		}
	}
}

/* Parse a statement (C90 6.6, C99 6.8).

statement:
labeled-statement
compound-statement
expression-statement
selection-statement
iteration-statement
jump-statement

labeled-statement:
label statement

expression-statement:
expression[opt] ;

selection-statement:
if-statement
switch-statement

iteration-statement:
while-statement
do-statement
for-statement

jump-statement:
goto identifier ;
continue ;
break ;
return expression[opt] ;

GNU extensions:

statement:
asm-statement

jump-statement:
goto * expression ;

Objective-C:

statement:
objc-throw-statement
objc-try-catch-statement
objc-synchronized-statement

objc-throw-statement:
@throw expression ;
@throw ;

OpenMP:

statement:
openmp-construct

openmp-construct:
parallel-construct
for-construct
sections-construct
single-construct
parallel-for-construct
parallel-sections-construct
master-construct
critical-construct
atomic-construct
ordered-construct

parallel-construct:
parallel-directive structured-block

for-construct:
for-directive iteration-statement

sections-construct:
sections-directive section-scope

single-construct:
single-directive structured-block

parallel-for-construct:
parallel-for-directive iteration-statement

parallel-sections-construct:
parallel-sections-directive section-scope

master-construct:
master-directive structured-block

critical-construct:
critical-directive structured-block

atomic-construct:
atomic-directive expression-statement

ordered-construct:
ordered-directive structured-block  */

static void jal_parser_statement (jal_parser *parser)
{
	while ( jal_parser_next_token_is_keyword (parser, RID_OTHERWISE)
		|| (jal_parser_next_token_is (parser, CPP_NAME)
		&& jal_parser_peek_2nd_token (parser)->type == CPP_COLON))
		jal_parser_label (parser);
	jal_parser_statement_after_labels (parser);
}

/* Parse a statement, other than a labeled statement.  */

static void jal_parser_statement_after_labels (jal_parser *parser)
{
	location_t loc = jal_parser_peek_token (parser)->location;
	tree stmt = NULL_TREE;
	bool in_if_block = parser->in_if_block;
	parser->in_if_block = false;

	jal_parser_trace0(  "TRACE: jal_parser_statement_after_labels " );

	switch (jal_parser_peek_token (parser)->type)
	{
	case CPP_KEYWORD:
		switch (jal_parser_peek_token (parser)->keyword)
		{
		case RID_BLOCK:
			//jal_parser_trace0(  "TRACE: RID_BLOCK " );
			jal_parser_block_statement( parser );
			break;
		case RID_IF:
			jal_parser_if_statement (parser, true);
			break;
		case RID_VAR:
			jal_parser_var_delcaration (parser);
			break;

		case RID_PRAGMA:
			jal_parser_pragma1 ( parser );
			break;

		case RID_PROCEDURE:
			jal_parser_procedure_or_function (parser, false, true );
			break;
		case RID_FUNCTION:
			jal_parser_procedure_or_function (parser, true, true );
			break;
		case RID_CONST:
			jal_parser_const_delcaration (parser);
			break;

		case RID_CASE:
			jal_parser_case_statement (parser);
			break;
		case RID_WHILE:
			jal_parser_while_statement (parser);
			break;
		case RID_REPEAT:
			jal_parser_repeat_until_statement (parser);
			break;
		case RID_FOR:
			jal_parser_for_statement (parser);
			break;
		case RID_FOREVER:
			jal_parser_forever_statement (parser);
			break;
		case RID_ALIAS:
			jal_parser_alias(parser);
			break;
		case RID_GOTO:
			jal_parser_consume_token (parser);
			if (jal_parser_next_token_is (parser, CPP_NAME))
			{
				stmt = jal_finish_goto_label (jal_parser_peek_token (parser)->value);
				jal_parser_consume_token (parser);
			}
			else if (jal_parser_next_token_is (parser, CPP_MULT))
			{
				jal_parser_trace0(  "RID_GOTO CPP MULT " );

				jal_parser_consume_token (parser);
				stmt = jal_finish_goto_ptr (jal_parser_expression (parser).value);
			}
			else
				jal_parser_error (parser, "expected identifier or %<*%>");
			goto expect_nothing;
		case RID_CONTINUE:
			jal_parser_consume_token (parser);
			stmt = jal_finish_bc_stmt (&jal_cont_label, false);
			goto expect_nothing;
		case RID_EXIT:
			jal_parser_consume_token (parser);
			jal_parser_require_keyword (parser, RID_LOOP, "expected %<exit loop%>");

			stmt = jal_finish_bc_stmt (&jal_break_label, true);
			goto expect_nothing;

		case RID_RETURN:
			jal_parser_consume_token (parser);
			if (jal_parser_next_token_is (parser, CPP_SEMICOLON))
			{
				stmt = jal_finish_return (NULL_TREE);
				jal_parser_consume_token (parser);
			}
			else
			{
				stmt = jal_finish_return (jal_parser_expression_conv (parser).value);
				goto expect_nothing;
			}
			break;
		case RID_ASM:
			stmt = jal_parser_asm_statement (parser);
			break;
		default:
			goto expr_stmt;
		}
		break;
	case CPP_SEMICOLON:
		//jal_parser_trace0(  "TRACE: CPP_SEMICOLON:, consume token" );
		jal_parser_consume_token (parser);
		break;
	case CPP_CLOSE_PAREN:
	case CPP_CLOSE_SQUARE:
		/* Avoid infinite loop in error recovery:
		jal_parser_skip_until_found stops at a closing nesting
		delimiter without consuming it, but here we need to consume
		it to proceed further.  */
		jal_parser_error (parser, "expected statement");
		jal_parser_consume_token (parser);
		break;
	case CPP_PRAGMA:
		jal_parser_pragma (parser, pragma_stmt);
		break;
	default:
		//jal_parser_trace0(  "TRACE: DEFAULT: " );
expr_stmt:
		jal_parser_trace0(  "TRACE: expr_stmt: " );
		stmt = jal_finish_expr_stmt (jal_parser_expression_conv (parser).value);
		// expect_semicolon:
		//jal_parser_trace0(  "TRACE: SKIP expect_semicolon: " );
		//	jal_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
expect_nothing:
		//jal_parser_trace0(  "TRACE: expect_nothing: " );
		break;
	}

	/* Two cases cannot and do not have line numbers associated: If stmt
	is degenerate, such as "2;", then stmt is an INTEGER_CST, which
	cannot hold line numbers.  But that's OK because the statement
	will either be changed to a MODIFY_EXPR during gimplification of
	the statement expr, or discarded.  If stmt was compound, but
	without new variables, we will have skipped the creation of a
	BIND and will have a bare STATEMENT_LIST.  But that's OK because
	(recursively) all of the component statements should already have
	line numbers assigned.  ??? Can we discard no-op statements
	earlier?  */
	if (stmt && CAN_HAVE_LOCATION_P (stmt))
		SET_EXPR_LOCATION (stmt, loc);

	parser->in_if_block = in_if_block;
}

/* Parse a parenthesized condition from an if, do or while statement.

condition:
( expression )
*/

// AF TOODO, refactor

static tree
jal_parser_condition (jal_parser *parser)
{
	location_t loc;
	tree cond;

	loc = jal_parser_peek_token (parser)->location;
	cond = c_objc_common_truthvalue_conversion
		(loc, jal_parser_expression_conv (parser).value);
	if (CAN_HAVE_LOCATION_P (cond))
		SET_EXPR_LOCATION (cond, loc);

	return cond;
}


/* Parse a statement which is a block in C99.  */

static tree
jal_parser_c99_block_statement (jal_parser *parser)
{
	tree block = jal_begin_compound_stmt (flag_isoc99);
	jal_parser_statement (parser);
	return c_end_compound_stmt (block, flag_isoc99);
}


static void jal_parser_var_declaration( jal_parser *parser, bool empty_ok, bool nested, bool start_attr_ok)
{
	struct jal_declspecs *specs;
	tree prefix_attrs;	
	tree all_prefix_attrs;
	bool diagnosed_no_specs = false;
	tree asm_name = NULL_TREE;
	tree postfix_attrs = NULL_TREE;

	//location_t here = jal_parser_peek_token (parser)->location;
	struct jal_declarator *declarator;
	bool dummy = false;

	empty_ok = empty_ok;
	nested = nested;
	start_attr_ok = start_attr_ok; 

	specs = build_null_declspecs ();

	jal_parser_trace0(  "jal_parser_declspecs C7" );

	jal_parser_parse_var_type(parser, specs, true);

	if (parser->error)
	{
		jal_parser_skip_to_end_of_block_or_statement (parser);
		return;
	}

	finish_declspecs (specs);

	pending_xref_error ();
	prefix_attrs = specs->attrs;
	all_prefix_attrs = prefix_attrs;
	specs->attrs = NULL_TREE;
	
	/* Declaring either one or more declarators (in which case we
	should diagnose if there were no declaration specifiers) or a
	function definition (in which case the diagnostic for
	implicit int suffices).  */
	declarator = jal_parser_direct_declarator (parser, specs->type_seen_p, C_DTR_NORMAL, &dummy);

	if (declarator == NULL)
	{
		jal_parser_trace0(  "WHILE DECL 3" );
		jal_parser_skip_to_end_of_block_or_statement (parser);
		return;
	}

	if (!diagnosed_no_specs && !specs->declspecs_seen_p)
	{
		diagnosed_no_specs = true;
		//pedwarn ("%Hdata definition has no type or storage class",
		//	&here);
	}

	/* check for initial assignment */
	if ( jal_parser_next_token_is (parser, CPP_EQ) || jal_parser_next_token_is_keyword (parser, RID_AT) )
	{
		tree d;
		struct jal_expr init;
		jal_parser_trace0(  "WHILE DECL 5" );

		if ( jal_parser_next_token_is_keyword (parser, RID_AT) )
		{
			struct jal_declspecs *quals_attrs = build_null_declspecs ();
			jal_parser_trace0(  "WHILE DECL 5a" );
			declarator = make_pointer_declarator (quals_attrs, declarator);
		}

		jal_parser_consume_token (parser);
		/* The declaration of the variable is in effect while
		its initializer is parsed.  */
		d = start_decl (declarator, specs, true, chainon (postfix_attrs, all_prefix_attrs));
		
		if (!d)
			d = error_mark_node;
		start_init (d, asm_name, global_bindings_p ());
		init = jal_parser_initializer (parser);
		finish_init ();
		if (d != error_mark_node)
		{
			maybe_warn_string_init (TREE_TYPE (d), init);
			finish_decl (d, init.value, asm_name);
		}
	}
	else
	{
		tree d = start_decl (declarator, specs, false,
			chainon (postfix_attrs,
			all_prefix_attrs));
		jal_parser_trace0(  "WHILE DECL 6" );
		if (d)
			finish_decl (d, NULL_TREE, asm_name);
	}
}

static void jal_parser_var_delcaration( jal_parser *parser )
{
	// consume token
	jal_parser_trace0(  "TRACE: jal_parser_var_delcaration " );
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_VAR ));
	jal_parser_consume_token (parser);
	jal_parser_var_declaration(parser, true, true, true);
	jal_parser_trace0(  "TRACE: jal_parser_var_delcaration done" );
}

static void jal_parser_const_delcaration( jal_parser *parser )
{
	bool empty_ok = true;
	bool nested = true;
	bool start_attr_ok = true;
	struct jal_declspecs *specs;
	tree prefix_attrs;
	tree all_prefix_attrs;
	bool diagnosed_no_specs = false;
	//location_t here = jal_parser_peek_token (parser)->location;
	struct jal_declarator *declarator;
	bool dummy = false;
	tree asm_name = NULL_TREE;
	tree postfix_attrs = NULL_TREE;

	specs = build_null_declspecs ();

	jal_parser_trace0(  "jal_parser_declspecs CONST VOLATILE " );

	declspecs_add_qual (specs, jal_parser_peek_token (parser)->value);
	jal_parser_consume_token (parser);			

	jal_parser_declspecs (parser, specs, true, true, start_attr_ok);

	if (parser->error)
	{
		jal_parser_skip_to_end_of_block_or_statement (parser);
		return;
	}
	if (nested && !specs->declspecs_seen_p)
	{
		jal_parser_error (parser, "expected declaration specifiers");
		jal_parser_skip_to_end_of_block_or_statement (parser);
		return;
	}
	finish_declspecs (specs);

	if (jal_parser_next_token_is (parser, CPP_SEMICOLON))
	{
		jal_parser_trace0(  "EMPTY VAR DECL" );
		if (empty_ok)
			shadow_tag (specs);
		else
		{
			shadow_tag_warned (specs, 1);
			//pedwarn ("%Hempty declaration", &here);
		}
		jal_parser_consume_token (parser);
		return;
	}

	pending_xref_error ();
	prefix_attrs = specs->attrs;
	all_prefix_attrs = prefix_attrs;
	specs->attrs = NULL_TREE;
	
	jal_parser_trace0(  "IN WHILE DECL LOOP 1" );

	/* Declaring either one or more declarators (in which case we
	should diagnose if there were no declaration specifiers) or a
	function definition (in which case the diagnostic for
	implicit int suffices).  */
	declarator = jal_parser_declarator (parser, specs->type_seen_p, C_DTR_NORMAL, &dummy);
	if (declarator == NULL)
	{
		jal_parser_trace0(  "WHILE DECL 3" );
		jal_parser_skip_to_end_of_block_or_statement (parser);
		return;
	}

	jal_parser_trace0(  "WHILE DECL 2" );
	if (!diagnosed_no_specs && !specs->declspecs_seen_p)
	{
		diagnosed_no_specs = true;
		//pedwarn ("%Hdata definition has no type or storage class",
		//	&here);
	}

	/* check for initial assignment */
	if (jal_parser_next_token_is (parser, CPP_EQ))
	{
		tree d;
		struct jal_expr init;
		jal_parser_trace0(  "WHILE DECL 5" );

		jal_parser_consume_token (parser);
		/* The declaration of the variable is in effect while
		its initializer is parsed.  */
		d = start_decl (declarator, specs, true,
			chainon (postfix_attrs, all_prefix_attrs));
		if (!d)
			d = error_mark_node;
		start_init (d, asm_name, global_bindings_p ());
		init = jal_parser_initializer (parser);
		finish_init ();
		if (d != error_mark_node)
		{
			maybe_warn_string_init (TREE_TYPE (d), init);
			finish_decl (d, init.value, asm_name);
		}
	}
	else
	{
		jal_parser_trace0(  "expect const initializer" );
	}
}



/* Parse an if statement (C90 6.6.4, C99 6.8.4).

if-statement:
if ( expression ) statement
if ( expression ) statement else statement
*/

static tree jal_parser_if_statement (jal_parser *parser, bool isIf)
{
	tree block;
	location_t loc;
	tree cond;
	bool first_if = false;
	tree first_body, second_body;
	bool in_if_block;
	tree elif_block = NULL;


	if ( isIf )
	{
		first_if = true;
		gcc_assert (jal_parser_next_token_is_keyword (parser, RID_IF));
	}
	else
	{
		elif_block = jal_begin_compound_stmt (flag_isoc99);
		first_if = true;
		gcc_assert (jal_parser_next_token_is_keyword (parser, RID_ELSIF));
	}

	jal_parser_consume_token (parser);
	block = jal_begin_compound_stmt (flag_isoc99);
	loc = jal_parser_peek_token (parser)->location;
	cond = jal_parser_condition (parser);
	in_if_block = parser->in_if_block;
	parser->in_if_block = true;

	jal_parser_require_keyword( parser, RID_THEN, "expected %<then%>" );
	first_body = jal_parser_compound_statement( parser );

	parser->in_if_block = in_if_block;

	if (jal_parser_next_token_is_keyword (parser, RID_ELSE))
	{
		jal_parser_consume_token (parser);
		second_body = jal_parser_compound_statement( parser );
		jal_parser_require_keyword (parser, RID_IF, "expected %<end if%>");
	}
	else if (jal_parser_next_token_is_keyword (parser, RID_ELSIF))
	{
		jal_parser_trace0(  "TRACE, ELSIF, set ELSE PART to recurse for this block" );
		second_body = jal_parser_if_statement (parser, false);
	}
	else
	{
		second_body = NULL_TREE;
		jal_parser_require_keyword (parser, RID_IF, "expected %<end if%>");
	}

	jal_finish_if_stmt (loc, cond, first_body, second_body, first_if);
	add_stmt (c_end_compound_stmt (block, flag_isoc99));

	if ( elif_block != NULL ) 
	{
		return c_end_compound_stmt (elif_block, flag_isoc99);
	}
	else
	{
		return NULL;
	}
}


static tree jal_parser_switch_body (jal_parser *parser);
static void jal_parser_case_label (jal_parser *parser);

static void jal_parser_case_label (jal_parser *parser)
{
	location_t loc1 = jal_parser_peek_token (parser)->location;
	tree label = NULL_TREE;

	jal_parser_trace0(  "jal_parser_case_label 1" );

	if (!jal_parser_next_token_is_keyword (parser, RID_OTHERWISE))
	{
		tree exp1;
		jal_parser_trace0(  "jal_parser_case_label 2" );

				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM P" );

		exp1 = jal_parser_expr_no_commas (parser, NULL).value;

		if (jal_parser_next_token_is (parser, CPP_COLON))
		{
			jal_parser_consume_token (parser);
			label = do_case (exp1, NULL_TREE);
		}
		else
		{
			jal_parser_error (parser, "expected %<:%> or %<...%>");
		}
	}
	else
	{
		jal_parser_trace0(  "jal_parser_case_label 6" );

		jal_parser_consume_token (parser);
		label = do_case (NULL_TREE, NULL_TREE);
	}

	if (label)
	{
		SET_EXPR_LOCATION (label, loc1);

		jal_parser_trace0(  "jal_parser_case_label 8" );

		if (jal_parser_next_token_starts_declspecs (parser)
			&& !(jal_parser_next_token_is (parser, CPP_NAME)
			&& jal_parser_peek_2nd_token (parser)->type == CPP_COLON))
		{
			error ("%Ha label can only be part of a statement and a declaration is not a statement",
				&jal_parser_peek_token (parser)->location);
			jal_parser_procedure_or_function (	parser, true, false );
		}
	}
	jal_parser_trace0(  "jal_parser_case_label 9" );
}


static tree jal_parser_switch_body (jal_parser *parser)
{
	tree stmt;

	jal_parser_trace0(  "jal_parser_switch_body 1" );

	stmt = jal_begin_compound_stmt (true);
	
	while ( !jal_parser_next_token_is_keyword (parser, RID_END) )
	{
		if ( jal_parser_next_token_is (parser, CPP_EOF) )
		{
			break;
		}
		jal_parser_trace0(  "jal_parser_switch_body 3" );
		jal_parser_case_label( parser );
		jal_parser_trace0(  "jal_parser_switch_body 4" );
		jal_parser_statement_after_labels( parser );
		jal_parser_trace0(  "jal_parser_switch_body 5" );
		jal_finish_bc_stmt (&jal_break_label, true);
		jal_parser_trace0(  "jal_parser_switch_body 5a" );
	}

	jal_parser_require_keyword (parser, RID_END, "expected %<end case%>");
	jal_parser_require_keyword (parser, RID_CASE, "expected %<end case%>");

	jal_parser_trace0(  "jal_parser_switch_body 6" );

	return c_end_compound_stmt (stmt, true);
}





/* Parse a case statement

case-statement:
case expression of case_body
*/

static void
jal_parser_case_statement (jal_parser *parser)
{
	tree block, expr, body, save_break;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_CASE));

	jal_parser_trace0(  "jal_parser_case_statement 1" );

	jal_parser_consume_token (parser);
	block = jal_begin_compound_stmt (flag_isoc99);

    expr = jal_parser_expression (parser).value;
	jal_parser_trace0(  "jal_parser_case_statement 2" );
	
	jal_start_case (expr);
	save_break = jal_break_label;
	jal_break_label = NULL_TREE;

	jal_parser_require_keyword (parser, RID_OF, "expected %<case of%>");

	body = jal_parser_switch_body( parser );

	jal_parser_trace0(  "jal_parser_case_statement 3" );

	jal_finish_case (body);


	if (jal_break_label)
	{
		add_stmt (build1 (LABEL_EXPR, void_type_node, jal_break_label));
	}

	jal_break_label = save_break;
	add_stmt (c_end_compound_stmt (block, flag_isoc99));

	jal_parser_trace0(  "jal_parser_case_statement 5" );
}


/* Parse a while statement

while-statement:
while expression do loop statements end loop
*/

static void jal_parser_while_statement (jal_parser *parser)
{
	tree block, cond, body, save_break, save_cont;
	location_t loc;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_WHILE));
	jal_parser_consume_token (parser);
	block = jal_begin_compound_stmt (flag_isoc99);
	loc = jal_parser_peek_token (parser)->location;
	cond = jal_parser_condition (parser);
	save_break = jal_break_label;
	jal_break_label = NULL_TREE;
	save_cont = jal_cont_label;
	jal_cont_label = NULL_TREE;

	jal_parser_require_keyword (parser, RID_LOOP, "expected %<loop%>");
	body = jal_parser_compound_statement (parser);
	jal_parser_require_keyword (parser, RID_LOOP, "expected %<end loop%>");

	jal_finish_loop (loc, cond, NULL, body, jal_break_label, jal_cont_label, true);

	add_stmt (c_end_compound_stmt (block, flag_isoc99));
	jal_break_label = save_break;
	jal_cont_label = save_cont;
}


static void jal_parser_block_statement( jal_parser *parser )
{
	tree body, block;
	block = jal_begin_compound_stmt (flag_isoc99);

	gcc_assert( jal_parser_next_token_is_keyword (parser, RID_BLOCK) );

	jal_parser_consume_token (parser);
	body = jal_parser_compound_statement (parser);
	jal_parser_require_keyword (parser, RID_BLOCK, "expected %<end  block%>");
	add_stmt( body );
	add_stmt (c_end_compound_stmt (block, flag_isoc99));
}


/* Parse a do statement (C90 6.6.5, C99 6.8.5).

do-statement:
do statement while ( expression ) ;
*/

static void jal_parser_repeat_until_statement (jal_parser *parser)
{
	tree block, cond, body, save_break, save_cont, new_break, new_cont;
	location_t loc;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_DO));
	jal_parser_consume_token (parser);

	//if (jal_parser_next_token_is (parser, CPP_SEMICOLON))
	//  warning (OPT_Wempty_body,
	//           "%Hsuggest braces around empty body in %<do%> statement",
	//     &jal_parser_peek_token (parser)->location);
	block = jal_begin_compound_stmt (flag_isoc99);

	// AF FINISH

	loc = jal_parser_peek_token (parser)->location;
	save_break = jal_break_label;
	jal_break_label = NULL_TREE;
	save_cont = jal_cont_label;
	jal_cont_label = NULL_TREE;
	body = jal_parser_c99_block_statement (parser);
	jal_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
	new_break = jal_break_label;
	jal_break_label = save_break;
	new_cont = jal_cont_label;
	jal_cont_label = save_cont;
	cond = jal_parser_condition (parser);
	if (!jal_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
		jal_parser_skip_to_end_of_block_or_statement (parser);
	jal_finish_loop (loc, cond, NULL, body, new_break, new_cont, false);
	add_stmt (c_end_compound_stmt (block, flag_isoc99));
}

/* Parse a for statement (C90 6.6.5, C99 6.8.5).

for-statement:
for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
for ( nested-declaration expression[opt] ; expression[opt] ) statement

The form with a declaration is new in C99.

??? In accordance with the old parser, the declaration may be a
nested function, which is then rejected in check_for_loop_decls,
but does it make any sense for this to be included in the grammar?
Note in particular that the nested function does not include a
trailing ';', whereas the "declaration" production includes one.
Also, can we reject bad declarations earlier and cheaper than
check_for_loop_decls?  */


static void
jal_parser_for_statement (jal_parser *parser)
{
	tree block, cond, body, save_break, save_cont, loop_cnt;
	location_t loc;
	tree init_val;
	tree int_type;
	tree loop_var;
	tree incr_var;

	PARSER_TRACE_ENTER();

	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_FOR));
	loc = jal_parser_peek_token (parser)->location;
	jal_parser_consume_token (parser);

	block = jal_begin_compound_stmt (flag_isoc99);

	save_break = jal_break_label;
	jal_break_label = NULL_TREE;
	save_cont = jal_cont_label;
	jal_cont_label = NULL_TREE;


	loop_cnt = jal_parser_postfix_expression (parser).value;


	if (jal_parser_next_token_is_keyword (parser, RID_USING))
	{

		jal_parser_trace0( "jal_parser_for_statement USING" );

		jal_parser_consume_token (parser);

		loop_var = jal_parser_postfix_expression (parser).value;
	}
	else
	{
		long loops = TREE_INT_CST_LOW (loop_cnt);

		// make dummy loop decl
		jal_parser_trace0( "jal_parser_for_statement make implicit loop variable" );
	   
		if ( TREE_INT_CST_LOW (loop_cnt) < 256 )
		{
			loop_var = make_implicit_var(parser, "byte");
			jal_parser_trace( "jal_parser_for_statement make implicit variable byte (loops = %d)",  loops );
		}
		else if ( loops < 65536 )
		{
			loop_var = make_implicit_var(parser, "word" );
			jal_parser_trace( "jal_parser_for_statement make implicit variable word (loops = %d)", loops );
		}
		else
		{
			loop_var = make_implicit_var(parser, "dword" );
			jal_parser_trace( "jal_parser_for_statement make implicit variable dword (loops = %d)", loops );
		}

		jal_parser_trace0( "jal_parser_for_statement make implicit loop variable DONE" );
	}

	int_type = integer_types[itk_int];
	init_val = build_int_cst_wide (int_type, 0, 0);

	// set loop counter to 0
	add_stmt( build_modify_expr (	0, loop_var, NOP_EXPR, init_val) );

	jal_parser_require_keyword (parser, RID_LOOP, "expected %<loop%>");

	jal_parser_trace0( "jal_parser_for_statement body start" );
	body = jal_parser_compound_statement (parser);
	jal_parser_trace0( "jal_parser_for_statement body end" );

	jal_parser_peek_token (parser);

	jal_print_token (stderr, &parser->tokens[0]);

	jal_parser_require_keyword (parser, RID_LOOP, "expected %<end loop%>");

	// build < numloops expresion
	cond = build_binary_op (loc, LT_EXPR,loop_var, loop_cnt, 0);


	incr_var = build_unary_op (loc,PREINCREMENT_EXPR, loop_var, 0);


	// similiar to while loop
	jal_finish_loop (loc, cond, incr_var, body, jal_break_label, jal_cont_label, true);

	add_stmt (c_end_compound_stmt (block, flag_isoc99));
	jal_break_label = save_break;
	jal_cont_label = save_cont;

	PARSER_TRACE_EXIT()

}


static void jal_parser_alias( jal_parser *parser )
{
						  
	tree alias_name;
	tree alias_value;

	jal_parser_trace0(  "jal_parser_alias ENTRY" );

	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_ALIAS));
	jal_parser_consume_token (parser);

	if ( jal_aliases_len + 1 >  jal_aliases_alloc )
	{
		jal_parser_trace0(  "jal_parser_alias REALLOC vector" );
		jal_alias_realloc();
	}

	if (	jal_parser_next_token_is (parser, CPP_NAME)
			&& ( jal_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
				|| jal_parser_peek_token (parser)->id_kind == C_ID_ID ) )
	{
		jal_parser_trace0(  "jal_parser_alias name" );
		alias_name = jal_parser_peek_token (parser)->value;
		jal_parser_consume_token (parser);
	}
	else
	{
		jal_parser_error(  parser,"expected alias name" );
		// AF FIXME
		jal_parser_skip_until_found (parser, CPP_OPEN_PAREN, NULL);
		return;
	}


	if ( jal_parser_require_keyword (parser, RID_IS, "expected %<is%>") == false )
	{
		jal_parser_trace0(  "jal_parser_alias missing is" );
		return;
	}

	if (	jal_parser_next_token_is (parser, CPP_NAME)
			&& ( jal_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
				|| jal_parser_peek_token (parser)->id_kind == C_ID_ID ) )
	{
		jal_parser_trace0(  "jal_parser_alias value" );
		alias_value = jal_parser_peek_token (parser)->value;
		jal_parser_consume_token (parser);
	}
	else
	{
		jal_parser_error(  parser,"expected alias value" );
		return;
	}

	jal_aliases_ptr[ jal_aliases_len ].alias_name = alias_name;
	jal_aliases_ptr[ jal_aliases_len ].alias_value = alias_value;
	jal_aliases_len++;
	jal_parser_trace0(  "jal_parser_alias EXIT" );

}



static void jal_parser_forever_statement (jal_parser *parser)
{
	tree block, cond, body, save_break, save_cont;
	location_t loc;

	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_FOREVER));
	jal_parser_consume_token (parser);
	block = jal_begin_compound_stmt (flag_isoc99);
	loc = jal_parser_peek_token (parser)->location;
	cond = truthvalue_true_node;

	save_break = jal_break_label;
	jal_break_label = NULL_TREE;
	save_cont = jal_cont_label;
	jal_cont_label = NULL_TREE;

	jal_parser_require_keyword (parser, RID_LOOP, "expected %<loop%>");
	body = jal_parser_compound_statement (parser);
	jal_parser_require_keyword (parser, RID_LOOP, "expected %<end loop%>");


	jal_finish_loop (loc, cond, NULL, body, jal_break_label, jal_cont_label, true);
	add_stmt (c_end_compound_stmt (block, flag_isoc99));
	jal_break_label = save_break;
	jal_cont_label = save_cont;
}


/* Parse an asm statement, a GNU extension.  This is a full-blown asm
statement with inputs, outputs, clobbers, and volatile tag
allowed.

asm-statement:
asm type-qualifier[opt] ( asm-argument ) ;

asm-argument:
asm-string-literal
asm-string-literal : asm-operands[opt]
asm-string-literal : asm-operands[opt] : asm-operands[opt]
asm-string-literal : asm-operands[opt] : asm-operands[opt] : asm-clobbers

Qualifiers other than volatile are accepted in the syntax but
warned for.  */

static tree
jal_parser_asm_statement (jal_parser *parser)
{
	tree quals, str, outputs, inputs, clobbers, ret;
	bool simple;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_ASM));
	jal_parser_consume_token (parser);
	if (jal_parser_next_token_is_keyword (parser, RID_VOLATILE))
	{
		quals = jal_parser_peek_token (parser)->value;
		jal_parser_consume_token (parser);
	}
	else if (jal_parser_next_token_is_keyword (parser, RID_CONST)
		|| jal_parser_next_token_is_keyword (parser, RID_RESTRICT))
	{
		warning (0, "%H%E qualifier ignored on asm",
			&jal_parser_peek_token (parser)->location,
			jal_parser_peek_token (parser)->value);
		quals = NULL_TREE;
		jal_parser_consume_token (parser);
	}
	else
		quals = NULL_TREE;
	/* ??? Follow the C++ parser rather than using the
	lex_untranslated_string kludge.  */
	parser->lex_untranslated_string = true;
	if (!jal_parser_require (parser, CPP_OPEN_PAREN, "12 expected %<(%>"))
	{
		parser->lex_untranslated_string = false;
		return NULL_TREE;
	}
	str = jal_parser_asm_string_literal (parser);
	if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
	{
		simple = true;
		outputs = NULL_TREE;
		inputs = NULL_TREE;
		clobbers = NULL_TREE;
		goto done_asm;
	}
	if (!jal_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
	{
		parser->lex_untranslated_string = false;
		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
		return NULL_TREE;
	}
	simple = false;
	/* Parse outputs.  */
	if (jal_parser_next_token_is (parser, CPP_COLON)
		|| jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
		outputs = NULL_TREE;
	else
		outputs = jal_parser_asm_operands (parser, false);
	if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
	{
		inputs = NULL_TREE;
		clobbers = NULL_TREE;
		goto done_asm;
	}
	if (!jal_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
	{
		parser->lex_untranslated_string = false;
		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
		return NULL_TREE;
	}
	/* Parse inputs.  */
	if (jal_parser_next_token_is (parser, CPP_COLON)
		|| jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
		inputs = NULL_TREE;
	else
		inputs = jal_parser_asm_operands (parser, true);
	if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
	{
		clobbers = NULL_TREE;
		goto done_asm;
	}
	if (!jal_parser_require (parser, CPP_COLON, "expected %<:%> or %<)%>"))
	{
		parser->lex_untranslated_string = false;
		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
		return NULL_TREE;
	}
	/* Parse clobbers.  */
	clobbers = jal_parser_asm_clobbers (parser);
done_asm:
	parser->lex_untranslated_string = false;
	if (!jal_parser_require (parser, CPP_CLOSE_PAREN, "15 expected %<)%>"))
	{
		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
		return NULL_TREE;
	}
	if (!jal_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
		jal_parser_skip_to_end_of_block_or_statement (parser);
	ret = build_asm_stmt (quals, build_asm_expr (str, outputs, inputs,
		clobbers, simple));
	return ret;
}

/* Parse asm operands, a GNU extension.  If CONVERT_P (for inputs but
not outputs), apply the default conversion of functions and arrays
to pointers.

asm-operands:
asm-operand
asm-operands , asm-operand

asm-operand:
asm-string-literal ( expression )
[ identifier ] asm-string-literal ( expression )
*/

static tree
jal_parser_asm_operands (jal_parser *parser, bool convert_p)
{
	tree list = NULL_TREE;
	while (true)
	{
		tree name, str;
		struct jal_expr expr;
		if (jal_parser_next_token_is (parser, CPP_OPEN_SQUARE))
		{
			jal_parser_consume_token (parser);
			if (jal_parser_next_token_is (parser, CPP_NAME))
			{
				tree id = jal_parser_peek_token (parser)->value;
				jal_parser_consume_token (parser);
				name = build_string (IDENTIFIER_LENGTH (id),
					IDENTIFIER_POINTER (id));
			}
			else
			{
				jal_parser_error (parser, "expected identifier");
				jal_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
				return NULL_TREE;
			}
			jal_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
				"expected %<]%>");
		}
		else
			name = NULL_TREE;
		str = jal_parser_asm_string_literal (parser);
		if (str == NULL_TREE)
			return NULL_TREE;
		parser->lex_untranslated_string = false;
		if (!jal_parser_require (parser, CPP_OPEN_PAREN, "13 expected %<(%>"))
		{
			parser->lex_untranslated_string = true;
			return NULL_TREE;
		}
		expr = jal_parser_expression (parser);
		if (convert_p)
			expr = default_function_array_conversion (expr);
		parser->lex_untranslated_string = true;
		if (!jal_parser_require (parser, CPP_CLOSE_PAREN, "16 expected %<)%>"))
		{
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
			return NULL_TREE;
		}
		list = chainon (list, build_tree_list (build_tree_list (name, str),
			expr.value));
		if (jal_parser_next_token_is (parser, CPP_COMMA))
			jal_parser_consume_token (parser);
		else
			break;
	}
	return list;
}

/* Parse asm clobbers, a GNU extension.

asm-clobbers:
asm-string-literal
asm-clobbers , asm-string-literal
*/

static tree
jal_parser_asm_clobbers (jal_parser *parser)
{
	tree list = NULL_TREE;
	while (true)
	{
		tree str = jal_parser_asm_string_literal (parser);
		if (str)
			list = tree_cons (NULL_TREE, str, list);
		else
			return NULL_TREE;
		if (jal_parser_next_token_is (parser, CPP_COMMA))
			jal_parser_consume_token (parser);
		else
			break;
	}
	return list;
}

/* Parse an expression other than a compound expression; that is, an
assignment expression (C90 6.3.16, C99 6.5.16).  If AFTER is not
NULL then it is an Objective-C message expression which is the
primary-expression starting the expression as an initializer.

assignment-expression:
conditional-expression
unary-expression assignment-operator assignment-expression

assignment-operator: one of
= 

In GNU C we accept any conditional expression on the LHS and
diagnose the invalid lvalue rather than producing a syntax
error.  */

static struct jal_expr
jal_parser_expr_no_commas (jal_parser *parser, struct jal_expr *after)
{
	struct jal_expr lhs, rhs, ret;
	enum tree_code code;
	  location_t op_location;

	jal_parser_trace0(  "jal_parser_expr_no_commas 1" );

	gcc_assert (!after || c_dialect_objc ());
	lhs = jal_parser_binary_expression (parser, after);

	jal_parser_trace0(  "jal_parser_expr_no_commas 2" );

	op_location = jal_parser_peek_token (parser)->location;

	switch (jal_parser_peek_token (parser)->type)
	{
		case CPP_EQ:
			jal_parser_trace0(  "jal_parser_expr_no_commas 2A CPP_EQ" );
			code = NOP_EXPR;
			break;
		default:
			jal_parser_trace0(  "jal_parser_expr_no_commas 2B return LHS" );
			return lhs;
	}
	jal_parser_consume_token (parser);
	jal_parser_trace0(  "jal_parser_expr_no_commas 3" );

				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM R" );

	rhs = jal_parser_expr_no_commas (parser, NULL);

	jal_parser_trace0(  "jal_parser_expr_no_commas 4" );

	rhs = default_function_array_conversion (rhs);
	ret.value = build_modify_expr (op_location,lhs.value, code, rhs.value);
	if (code == NOP_EXPR)
		ret.original_code = MODIFY_EXPR;
	else
	{
		TREE_NO_WARNING (ret.value) = 1;
		ret.original_code = ERROR_MARK;
	}
	jal_parser_trace0(  "jal_parser_expr_no_commas 5" );

	return ret;
}

/* Parse a binary expression; that is, a logical-OR-expression (C90
6.3.5-6.3.14, C99 6.5.5-6.5.14).  If AFTER is not NULL then it is
an Objective-C message expression which is the primary-expression
starting the expression as an initializer.

multiplicative-expression:
cast-expression
multiplicative-expression * cast-expression
multiplicative-expression / cast-expression
multiplicative-expression % cast-expression

additive-expression:
multiplicative-expression
additive-expression + multiplicative-expression
additive-expression - multiplicative-expression

shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression

relational-expression:
shift-expression
relational-expression < shift-expression
relational-expression > shift-expression
relational-expression <= shift-expression
relational-expression >= shift-expression

equality-expression:
relational-expression
equality-expression == relational-expression
equality-expression != relational-expression

AND-expression:
equality-expression
AND-expression & equality-expression

exclusive-OR-expression:
AND-expression
exclusive-OR-expression ^ AND-expression

inclusive-OR-expression:
exclusive-OR-expression
inclusive-OR-expression | exclusive-OR-expression

logical-AND-expression:
inclusive-OR-expression
logical-AND-expression && inclusive-OR-expression

logical-OR-expression:
logical-AND-expression
logical-OR-expression || logical-AND-expression
*/

static struct jal_expr
jal_parser_binary_expression (jal_parser *parser, struct jal_expr *after)
{
	/* A binary expression is parsed using operator-precedence parsing,
	with the operands being cast expressions.  All the binary
	operators are left-associative.  Thus a binary expression is of
	form:

	E0 op1 E1 op2 E2 ...

	which we represent on a stack.  On the stack, the precedence
	levels are strictly increasing.  When a new operator is
	encountered of higher precedence than that at the top of the
	stack, it is pushed; its LHS is the top expression, and its RHS
	is everything parsed until it is popped.  When a new operator is
	encountered with precedence less than or equal to that at the top
	of the stack, triples E[i-1] op[i] E[i] are popped and replaced
	by the result of the operation until the operator at the top of
	the stack has lower precedence than the new operator or there is
	only one element on the stack; then the top expression is the LHS
	of the new operator.  In the case of logical AND and OR
	expressions, we also need to adjust skip_evaluation as
	appropriate when the operators are pushed and popped.  */

	/* The precedence levels, where 0 is a dummy lowest level used for
	the bottom of the stack.  */
	enum prec {
		PREC_NONE,
		PREC_LOGOR,
		PREC_LOGAND,
		PREC_BITOR,
		PREC_BITXOR,
		PREC_BITAND,
		PREC_EQ,
		PREC_REL,
		PREC_SHIFT,
		PREC_ADD,
		PREC_MULT,
		NUM_PRECS
	};
	struct {
		/* The expression at this stack level.  */
		struct jal_expr expr;
		/* The precedence of the operator on its left, PREC_NONE at the
		bottom of the stack.  */
		enum prec prec;
		/* The operation on its left.  */
		enum tree_code op;
	} stack[NUM_PRECS];
	int sp;

/* Location of the binary operator.  */
location_t binary_loc = UNKNOWN_LOCATION;  /* Quiet warning.  */
#define POP								      \
  do {									      \
    switch (stack[sp].op)						      \
      {									      \
      case TRUTH_ANDIF_EXPR:						      \
	skip_evaluation -= stack[sp - 1].expr.value == truthvalue_false_node; \
	break;								      \
      case TRUTH_ORIF_EXPR:						      \
	skip_evaluation -= stack[sp - 1].expr.value == truthvalue_true_node;  \
	break;								      \
      default:								      \
	break;								      \
      }									      \
    stack[sp - 1].expr							      \
      = default_function_array_conversion (stack[sp - 1].expr);		      \
    stack[sp].expr							      \
      = default_function_array_conversion (stack[sp].expr);		      \
    stack[sp - 1].expr = parser_build_binary_op (binary_loc,		      \
						 stack[sp].op,		      \
						 stack[sp - 1].expr,	      \
						 stack[sp].expr);	      \
    sp--;								      \
  } while (0)
  gcc_assert (!after || c_dialect_objc ());
  stack[0].expr = jal_parser_cast_expression (parser, after);
  stack[0].prec = PREC_NONE;
  sp = 0;
  while (true)
    {
      enum prec oprec;
      enum tree_code ocode;
      if (parser->error)
	goto out;
      switch (jal_parser_peek_token (parser)->type)
	{
	case CPP_MULT:
	  oprec = PREC_MULT;
	  ocode = MULT_EXPR;
	  break;
	case CPP_DIV:
	  oprec = PREC_MULT;
	  ocode = TRUNC_DIV_EXPR;
	  break;
	case CPP_MOD:
	  oprec = PREC_MULT;
	  ocode = TRUNC_MOD_EXPR;
	  break;
	case CPP_PLUS:
	  oprec = PREC_ADD;
	  ocode = PLUS_EXPR;
	  break;
	case CPP_MINUS:
	  oprec = PREC_ADD;
	  ocode = MINUS_EXPR;
	  break;
	case CPP_LSHIFT:
	  oprec = PREC_SHIFT;
	  ocode = LSHIFT_EXPR;
	  break;
	case CPP_RSHIFT:
	  oprec = PREC_SHIFT;
	  ocode = RSHIFT_EXPR;
	  break;
	case CPP_LESS:
	  oprec = PREC_REL;
	  ocode = LT_EXPR;
	  break;
	case CPP_GREATER:
	  oprec = PREC_REL;
	  ocode = GT_EXPR;
	  break;
	case CPP_LESS_EQ:
	  oprec = PREC_REL;
	  ocode = LE_EXPR;
	  break;
	case CPP_GREATER_EQ:
	  oprec = PREC_REL;
	  ocode = GE_EXPR;
	  break;
	case CPP_EQ_EQ:
	  oprec = PREC_EQ;
	  ocode = EQ_EXPR;
	  break;
	case CPP_NOT_EQ:
	  oprec = PREC_EQ;
	  ocode = NE_EXPR;
	  break;
	case CPP_AND:
	  oprec = PREC_BITAND;
	  ocode = BIT_AND_EXPR;
	  break;
	case CPP_XOR:
	  oprec = PREC_BITXOR;
	  ocode = BIT_XOR_EXPR;
	  break;
	case CPP_OR:
	  oprec = PREC_BITOR;
	  ocode = BIT_IOR_EXPR;
	  break;
	case CPP_AND_AND:
	  oprec = PREC_LOGAND;
	  ocode = TRUTH_ANDIF_EXPR;
	  break;
	case CPP_OR_OR:
	  oprec = PREC_LOGOR;
	  ocode = TRUTH_ORIF_EXPR;
	  break;
	default:
	  /* Not a binary operator, so end of the binary
	     expression.  */
	  goto out;
	}
      binary_loc = jal_parser_peek_token (parser)->location;
      jal_parser_consume_token (parser);
      while (oprec <= stack[sp].prec)
	POP;
      switch (ocode)
	{
	case TRUTH_ANDIF_EXPR:
	  stack[sp].expr
	    = default_function_array_conversion (stack[sp].expr);
	  stack[sp].expr.value = c_objc_common_truthvalue_conversion
	    (binary_loc, default_conversion (stack[sp].expr.value));
	  skip_evaluation += stack[sp].expr.value == truthvalue_false_node;
	  break;
	case TRUTH_ORIF_EXPR:
	  stack[sp].expr
	    = default_function_array_conversion (stack[sp].expr);
	  stack[sp].expr.value = c_objc_common_truthvalue_conversion
	    (binary_loc, default_conversion (stack[sp].expr.value));
	  skip_evaluation += stack[sp].expr.value == truthvalue_true_node;
	  break;
	default:
	  break;
	}
      sp++;
      stack[sp].expr = jal_parser_cast_expression (parser, NULL);
      stack[sp].prec = oprec;
      stack[sp].op = ocode;
    }
 out:
  while (sp > 0)
    POP;
  return stack[0].expr;
#undef POP
}

/* Parse a cast expression (C90 6.3.4, C99 6.5.4).  If AFTER is not
NULL then it is an Objective-C message expression which is the
primary-expression starting the expression as an initializer.

cast-expression:
unary-expression
( type-name ) unary-expression
*/

static struct jal_expr
jal_parser_cast_expression (jal_parser *parser, struct jal_expr *after)
{
	gcc_assert (!after || c_dialect_objc ());

	jal_parser_trace0(  "jal_parser_cast_expression ENTRY");

	if (after)
	{
		jal_parser_trace0(  "jal_parser_cast_expression 1");
		return jal_parser_postfix_expression_after_primary (parser, *after);
	}

	/* If the expression begins with a parenthesized type name, it may
	be either a cast or a compound literal; we need to see whether
	the next character is '{' to tell the difference.  If not, it is
	an unary expression.  */
// AF
	//if (jal_parser_next_token_is (parser, CPP_OPEN_PAREN)
	//	&& jal_token_starts_typename (jal_parser_peek_2nd_token (parser)))
	//{
	//	struct jal_type_name *type_name;
	//	struct jal_expr ret;
	//	struct jal_expr expr;
	//	jal_parser_consume_token (parser);
	//	type_name = jal_parser_type_name (parser);
	//	jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
	//	if (type_name == NULL)
	//	{
	//		ret.value = error_mark_node;
	//		ret.original_code = ERROR_MARK;
	//		return ret;
	//	}

	//	/* Save casted types in the function's used types hash table.  */
	//	used_types_insert (type_name->specs->type);

	//	if (jal_parser_next_token_is (parser, CPP_OPEN_BRACE))
	//		return jal_parser_postfix_expression_after_paren_type (parser,
	//		type_name);
	//	expr = jal_parser_cast_expression (parser, NULL);
	//	expr = default_function_array_conversion (expr);
	//	ret.value = jal_cast_expr (type_name, expr.value);
	//	ret.original_code = ERROR_MARK;
	//	return ret;
	//}
	//else

	// fprintf( stderr, "CHECK CAST!!!!!!!!!!!!!!\n");

	//jal_print_token (stderr, &parser->tokens[0]);

	if ( jal_parser_next_token_starts_typename( parser ) )
	{
		struct jal_type_name *type_name;
		struct jal_expr ret;
		struct jal_expr expr;

		jal_parser_trace0(  "jal_parser_cast_expression 2a");
		// jal_parser_consume_token (parser);

		g_isInCast = true;

		type_name = jal_parser_type_name (parser);

		g_isInCast = false;

		jal_parser_trace0(  "jal_parser_cast_expression 2b");
		
		// jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
		if (type_name == NULL)
		{
			ret.value = error_mark_node;
			ret.original_code = ERROR_MARK;
			return ret;
		}


		/* Save casted types in the function's used types hash table.  */
		used_types_insert (type_name->specs->type);

		if (jal_parser_next_token_is (parser, CPP_OPEN_BRACE))
			return jal_parser_postfix_expression_after_paren_type (parser,
			type_name);

		jal_parser_trace0(  "jal_parser_cast_expression 2c");

		expr = jal_parser_cast_expression (parser, NULL);

		jal_parser_trace0(  "jal_parser_cast_expression 2d");

		expr = default_function_array_conversion (expr);

		jal_parser_trace0(  "jal_parser_cast_expression 2e");

		ret.value = jal_cast_expr (type_name, expr.value);

		jal_parser_trace0(  "jal_parser_cast_expression 2f");

		ret.original_code = ERROR_MARK;
		return ret;

	}
	else
	{
		jal_parser_trace0(  "jal_parser_cast_expression 3");

		return jal_parser_unary_expression (parser);
	}
}

/* Parse an unary expression (C90 6.3.3, C99 6.5.3).

unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )

unary-operator: one of
& * + - ~ !

GNU extensions:

unary-expression:
__alignof__ unary-expression
__alignof__ ( type-name )
&& identifier

unary-operator: one of
__extension__ __real__ __imag__

In addition, the GNU syntax treats ++ and -- as unary operators, so
they may be applied to cast expressions with errors for non-lvalues
given later.  */

static struct jal_expr
jal_parser_unary_expression (jal_parser *parser)
{
	//int ext;
	struct jal_expr ret, op;
	location_t loc = jal_parser_peek_token (parser)->location;

	// jal_parser_trace0(  "\n CALLING jal_parser_unary_expression");

	switch (jal_parser_peek_token (parser)->type)
	{
	//case CPP_AND:
	//	jal_parser_consume_token (parser);
	//	return parser_build_unary_op (ADDR_EXPR,
	//		jal_parser_cast_expression (parser, NULL),loc);
	//case CPP_MULT:
	////	jal_parser_trace0(  "\n CALLING jal_parser_unary_expression mult                1");

	//	jal_parser_consume_token (parser);
	//	jal_parser_trace0(  "\n CALLING jal_parser_unary_expression CAST EXPRESSION     2");
	//	op = jal_parser_cast_expression (parser, NULL);
	////	jal_parser_trace0(  "\n CALLING default_function_array_conversion               3");
	//	op = default_function_array_conversion (op);
	////	jal_parser_trace0(  "\n CONVERT TO uNARY                                        4*");
	//	ret.value = build_indirect_ref (loc, op.value, "unary *");
	//	ret.original_code = ERROR_MARK;
	//	return ret;
	case CPP_PLUS:
		//if (!c_dialect_objc () && !in_system_header)
		//	warning (OPT_Wtraditional,
		//	"%Htraditional C rejects the unary plus operator",
		//	&jal_parser_peek_token (parser)->location);
		jal_parser_consume_token (parser);
		op = jal_parser_cast_expression (parser, NULL);
		op = default_function_array_conversion (op);
		return parser_build_unary_op (CONVERT_EXPR, op,loc);
	case CPP_MINUS:
		jal_parser_consume_token (parser);
		op = jal_parser_cast_expression (parser, NULL);
		op = default_function_array_conversion (op);
		return parser_build_unary_op (NEGATE_EXPR, op,loc);
	case CPP_COMPL:
		jal_parser_consume_token (parser);
		op = jal_parser_cast_expression (parser, NULL);
		op = default_function_array_conversion (op);
		return parser_build_unary_op (BIT_NOT_EXPR, op,loc);
	case CPP_NOT:
		jal_parser_consume_token (parser);
		op = jal_parser_cast_expression (parser, NULL);
		op = default_function_array_conversion (op);
		return parser_build_unary_op (TRUTH_NOT_EXPR, op,loc);
	case CPP_AND_AND:
		/* Refer to the address of a label as a pointer.  */
		jal_parser_consume_token (parser);
		if (jal_parser_next_token_is (parser, CPP_NAME))
		{
			ret.value = finish_label_address_expr
				(jal_parser_peek_token (parser)->value,loc);
			jal_parser_consume_token (parser);
		}
		else
		{
			jal_parser_error (parser, "expected identifier");
			ret.value = error_mark_node;
		}
		ret.original_code = ERROR_MARK;
		return ret;
	case CPP_KEYWORD:
		switch (jal_parser_peek_token (parser)->keyword)
		{
		case RID_SIZEOF:
			return jal_parser_sizeof_expression (parser);
		case RID_ALIGNOF:
			return jal_parser_alignof_expression (parser);
		default:
			return jal_parser_postfix_expression (parser);
		}
	default:
		// jal_parser_trace0(  "\n CALLING jal_parser_postfix_expression from default");
		return jal_parser_postfix_expression (parser);
	}
}

/* Parse a sizeof expression.  */

static struct jal_expr
jal_parser_sizeof_expression (jal_parser *parser)
{
	struct jal_expr expr;
	location_t expr_loc;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_SIZEOF));
	jal_parser_consume_token (parser);
	skip_evaluation++;
	in_sizeof++;
	if (jal_parser_next_token_is (parser, CPP_OPEN_PAREN)
		&& jal_token_starts_typename (jal_parser_peek_2nd_token (parser)))
	{
		/* Either sizeof ( type-name ) or sizeof unary-expression
		starting with a compound literal.  */
		struct jal_type_name *type_name;
		jal_parser_consume_token (parser);
		expr_loc = jal_parser_peek_token (parser)->location;
		type_name = jal_parser_type_name (parser);
		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "17 expected %<)%>");
		if (type_name == NULL)
		{
			struct jal_expr ret;
			skip_evaluation--;
			in_sizeof--;
			ret.value = error_mark_node;
			ret.original_code = ERROR_MARK;
			return ret;
		}
		if (jal_parser_next_token_is (parser, CPP_OPEN_BRACE))
		{
			expr = jal_parser_postfix_expression_after_paren_type (parser,
				type_name);
			goto sizeof_expr;
		}
		/* sizeof ( type-name ).  */
		skip_evaluation--;
		in_sizeof--;
		if (type_name->declarator->kind == cdk_array
			&& type_name->declarator->u.array.vla_unspec_p)
		{
			/* C99 6.7.5.2p4 */
			error ("%H%<[*]%> not allowed in other than a declaration",
				&expr_loc);
		}
		return jal_expr_sizeof_type (type_name);
	}
	else
	{
		expr_loc = jal_parser_peek_token (parser)->location;
		expr = jal_parser_unary_expression (parser);
sizeof_expr:
		skip_evaluation--;
		in_sizeof--;
		if (TREE_CODE (expr.value) == COMPONENT_REF
			&& DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
			error ("%H%<sizeof%> applied to a bit-field", &expr_loc);
		return jal_expr_sizeof_expr (expr);
	}
}

/* Parse an alignof expression.  */

static struct jal_expr
jal_parser_alignof_expression (jal_parser *parser)
{
	struct jal_expr expr;
	gcc_assert (jal_parser_next_token_is_keyword (parser, RID_ALIGNOF));
	jal_parser_consume_token (parser);
	skip_evaluation++;
	in_alignof++;
	if (jal_parser_next_token_is (parser, CPP_OPEN_PAREN)
		&& jal_token_starts_typename (jal_parser_peek_2nd_token (parser)))
	{
		/* Either __alignof__ ( type-name ) or __alignof__
		unary-expression starting with a compound literal.  */
		struct jal_type_name *type_name;
		struct jal_expr ret;
		jal_parser_consume_token (parser);
		type_name = jal_parser_type_name (parser);
		jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "1 expected %<)%>");
		if (type_name == NULL)
		{
			struct jal_expr ret;
			skip_evaluation--;
			in_alignof--;
			ret.value = error_mark_node;
			ret.original_code = ERROR_MARK;
			return ret;
		}
		if (jal_parser_next_token_is (parser, CPP_OPEN_BRACE))
		{
			expr = jal_parser_postfix_expression_after_paren_type (parser,
				type_name);
			goto alignof_expr;
		}
		/* alignof ( type-name ).  */
		skip_evaluation--;
		in_alignof--;
		ret.value = c_alignof (groktypename (type_name));
		ret.original_code = ERROR_MARK;
		return ret;
	}
	else
	{
		struct jal_expr ret;
		expr = jal_parser_unary_expression (parser);
alignof_expr:
		skip_evaluation--;
		in_alignof--;
		ret.value = c_alignof_expr (expr.value);
		ret.original_code = ERROR_MARK;
		return ret;
	}
}

/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2).

postfix-expression:
primary-expression
postfix-expression [ expression ]
postfix-expression ( argument-expression-list[opt] )
postfix-expression . identifier
postfix-expression -> identifier
postfix-expression ++
postfix-expression --
( type-name ) { initializer-list }
( type-name ) { initializer-list , }

argument-expression-list:
argument-expression
argument-expression-list , argument-expression

primary-expression:
identifier
constant
string-literal
( expression )

GNU extensions:

primary-expression:
__func__
(treated as a keyword in GNU C)
__FUNCTION__
__PRETTY_FUNCTION__
( compound-statement )
__builtin_va_arg ( assignment-expression , type-name )
__builtin_offsetof ( type-name , offsetof-member-designator )
__builtin_choose_expr ( assignment-expression ,
assignment-expression ,
assignment-expression )
__builtin_types_compatible_p ( type-name , type-name )

offsetof-member-designator:
identifier
offsetof-member-designator . identifier
offsetof-member-designator [ expression ]

Objective-C:

primary-expression:
[ objc-receiver objc-message-args ]
@selector ( objc-selector-arg )
@protocol ( identifier )
@encode ( type-name )
objc-string-literal
*/

static struct jal_expr
jal_parser_postfix_expression (jal_parser *parser)
{
	struct jal_expr expr, e1, e2, e3;
	struct jal_type_name *t1; //  *t2;
	location_t loc;

	jal_parser_trace0(  "jal_parser_postfix_expression ENTRY" );

	switch (jal_parser_peek_token (parser)->type)
	{
	case CPP_NUMBER:
	case CPP_CHAR:
		jal_parser_trace0(  "jal_parser_postfix_expression CPP_NUMBER/CPP_CHAR" );
		expr.value = jal_parser_peek_token (parser)->value;
		expr.original_code = ERROR_MARK;
		jal_parser_consume_token (parser);
		break;

    case CPP_STRING:
		jal_parser_trace0(  "jal_parser_postfix_expression CPP_STRING" );
		expr.value = jal_parser_peek_token (parser)->value;
		expr.original_code = STRING_CST;
		jal_parser_consume_token (parser);
		break;
	case CPP_NAME:
		jal_parser_trace0(  "jal_parser_postfix_expression CPP_NAME" );

		if (jal_parser_peek_token (parser)->id_kind != C_ID_ID)
		{
			jal_parser_error (parser, "1 expected expression");
			expr.value = error_mark_node;
			expr.original_code = ERROR_MARK;
			break;
		}
		// VARIABLE OR FUNCTION
		{
			tree id = jal_parser_peek_token (parser)->value;
			location_t loc = jal_parser_peek_token (parser)->location;
			jal_parser_consume_token (parser);
			expr.value = build_external_ref (id,
				(jal_parser_peek_token (parser)->type
				== CPP_OPEN_PAREN), loc);
			expr.original_code = ERROR_MARK;

			if ( TREE_CODE( TREE_TYPE( expr.value ) ) != FUNCTION_TYPE )
				{
				  tree pointer = default_conversion (expr.value);
				  tree type = TREE_TYPE (pointer);

				  if (TREE_CODE (type) == POINTER_TYPE)
					{
						jal_parser_trace0( "jal_parser_postfix_expression IS POINTER TYPE DEREFERENCE");

						// AF TODO expr = default_function_array_conversion (expr);
						// jal_parser_trace0(  "\n CONVERT TO uNARY                                        4*");
						expr.value = build_indirect_ref (loc,expr.value, "unary *");
						expr.original_code = ERROR_MARK;
				  }
				}
				else
				{
					jal_parser_trace( "jal_parser_postfix_expression IS FUNCTION %d", TREE_CODE (expr.value));
				}

		}
		break;
	case CPP_OPEN_PAREN:
		/* A parenthesized expression, statement expression or compound
		literal.  */
		jal_parser_trace0( "jal_parser_postfix_expression CPP_OPEN_PAREN" );
		if (jal_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
		{
			/* A statement expression.  */
			tree stmt;
			location_t here = jal_parser_peek_token (parser)->location;
			jal_parser_consume_token (parser);
			jal_parser_consume_token (parser);
			if (cur_stmt_list == NULL)
			{
				error ("%Hbraced-group within expression allowed "
					"only inside a function", &here);
				parser->error = true;
				jal_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
				jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
				expr.value = error_mark_node;
				expr.original_code = ERROR_MARK;
				break;
			}
			stmt = jal_begin_stmt_expr ();
			jal_parser_compound_statement_nostart (parser);
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
				"2 expected %<)%>");
			//if (pedantic)
			//	pedwarn ("%HISO C forbids braced-groups within expressions",
			//	&here);
			expr.value = jal_finish_stmt_expr (stmt);
			expr.original_code = ERROR_MARK;
		}
		else if (jal_token_starts_typename (jal_parser_peek_2nd_token (parser)))
		{
			/* A compound literal.  ??? Can we actually get here rather
			than going directly to
			jal_parser_postfix_expression_after_paren_type from
			elsewhere?  */
			struct jal_type_name *type_name;
			jal_parser_consume_token (parser);
			type_name = jal_parser_type_name (parser);
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
				"3 expected %<)%>");
			if (type_name == NULL)
			{
				expr.value = error_mark_node;
				expr.original_code = ERROR_MARK;
			}
			else
				expr = jal_parser_postfix_expression_after_paren_type (parser,
				type_name);
		}
		else
		{
			jal_parser_trace0( "jal_parser_postfix_expression A parenthesized expression" );
			/* A parenthesized expression.  */
			jal_parser_consume_token (parser);
			expr = jal_parser_expression (parser);
			if (TREE_CODE (expr.value) == MODIFY_EXPR)
				TREE_NO_WARNING (expr.value) = 1;
			expr.original_code = ERROR_MARK;
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
				"4 expected %<)%>");
		}
		break;
	case CPP_KEYWORD:
		switch (jal_parser_peek_token (parser)->keyword)
		{
		case RID_OFFSETOF:
			jal_parser_consume_token (parser);
			if (!jal_parser_require (parser, CPP_OPEN_PAREN, "2 expected %<(%>"))
			{
				expr.value = error_mark_node;
				expr.original_code = ERROR_MARK;
				break;
			}
			t1 = jal_parser_type_name (parser);
			if (t1 == NULL)
			{
				expr.value = error_mark_node;
				expr.original_code = ERROR_MARK;
				break;
			}
			if (!jal_parser_require (parser, CPP_COMMA, "expected %<,%>"))
			{
				jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
				expr.value = error_mark_node;
				expr.original_code = ERROR_MARK;
				break;
			}
			{
				tree type = groktypename (t1);
				tree offsetof_ref;
				if (type == error_mark_node)
					offsetof_ref = error_mark_node;
				else
					offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
				/* Parse the second argument to __builtin_offsetof.  We
				must have one identifier, and beyond that we want to
				accept sub structure and sub array references.  */
				if (jal_parser_next_token_is (parser, CPP_NAME))
				{
					offsetof_ref = build_component_ref
						(offsetof_ref, jal_parser_peek_token (parser)->value);
					jal_parser_consume_token (parser);
					while (jal_parser_next_token_is (parser, CPP_DOT)
						|| jal_parser_next_token_is (parser,
						CPP_OPEN_SQUARE))
					{
						if (jal_parser_next_token_is (parser, CPP_DOT))
						{
							jal_parser_consume_token (parser);
							if (jal_parser_next_token_is_not (parser,
								CPP_NAME))
							{
								jal_parser_error (parser, "expected identifier");
								break;
							}
							offsetof_ref = build_component_ref
								(offsetof_ref,
								jal_parser_peek_token (parser)->value);
							jal_parser_consume_token (parser);
						}
						else
						{
							tree idx;
							location_t loc = jal_parser_peek_token (parser)->location;
							jal_parser_consume_token (parser);

							idx = jal_parser_expression (parser).value;
							jal_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
								"expected %<]%>");
							offsetof_ref = build_array_ref (offsetof_ref, idx,loc);
						}
					}
				}
				else
					jal_parser_error (parser, "expected identifier");
				jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
					"5 expected %<)%>");
				expr.value = fold_offsetof (offsetof_ref, NULL_TREE);
				expr.original_code = ERROR_MARK;
			}
			break;
		case RID_CHOOSE_EXPR:
			jal_parser_consume_token (parser);
			if (!jal_parser_require (parser, CPP_OPEN_PAREN, "3 expected %<(%>"))
			{
				expr.value = error_mark_node;
				expr.original_code = ERROR_MARK;
				break;
			}
			loc = jal_parser_peek_token (parser)->location;
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM S" );

			e1 = jal_parser_expr_no_commas (parser, NULL);
			if (!jal_parser_require (parser, CPP_COMMA, "expected %<,%>"))
			{
				jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
				expr.value = error_mark_node;
				expr.original_code = ERROR_MARK;
				break;
			}
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM T" );

			e2 = jal_parser_expr_no_commas (parser, NULL);
			if (!jal_parser_require (parser, CPP_COMMA, "expected %<,%>"))
			{
				jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
				expr.value = error_mark_node;
				expr.original_code = ERROR_MARK;
				break;
			}
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM U" );

			e3 = jal_parser_expr_no_commas (parser, NULL);
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
				"6 expected %<)%>");
			{
				tree c;

				c = fold (e1.value);
				if (TREE_CODE (c) != INTEGER_CST)
					error ("%Hfirst argument to %<__builtin_choose_expr%> not"
					" a constant", &loc);
				expr = integer_zerop (c) ? e3 : e2;
			}
			break;
		default:
			jal_parser_error (parser, "2 expected expression");
			expr.value = error_mark_node;
			expr.original_code = ERROR_MARK;
			break;
		}
		break;
	case CPP_OPEN_SQUARE:
		/* Else fall through to report error.  */
	default:
		jal_parser_error (parser, "3 expected expression");
		expr.value = error_mark_node;
		expr.original_code = ERROR_MARK;
		break;
	}
	return jal_parser_postfix_expression_after_primary (parser, expr);
}

/* Parse a postfix expression after a parenthesized type name: the
brace-enclosed initializer of a compound literal, possibly followed
by some postfix operators.  This is separate because it is not
possible to tell until after the type name whether a cast
expression has a cast or a compound literal, or whether the operand
of sizeof is a parenthesized type name or starts with a compound
literal.  */

static struct jal_expr
jal_parser_postfix_expression_after_paren_type (jal_parser *parser,
struct jal_type_name *type_name)
{
	tree type;
	struct jal_expr init;
	struct jal_expr expr;
	location_t start_loc;
	start_init (NULL_TREE, NULL, 0);
	type = groktypename (type_name);
	start_loc = jal_parser_peek_token (parser)->location;
	if (type != error_mark_node && JAL_TYPE_VARIABLE_SIZE (type))
	{
		error ("%Hcompound literal has variable size", &start_loc);
		type = error_mark_node;
	}
	init = jal_parser_braced_init (parser, type, false);
	finish_init ();
	maybe_warn_string_init (type, init);

	//if (pedantic && !flag_isoc99)
	//	pedwarn ("%HISO C90 forbids compound literals", &start_loc);
	expr.value = build_compound_literal (type, init.value);
	expr.original_code = ERROR_MARK;
	return jal_parser_postfix_expression_after_primary (parser, expr);
}

/* Parse a postfix expression after the initial primary or compound
literal; that is, parse a series of postfix operators.  */

static struct jal_expr
jal_parser_postfix_expression_after_primary (jal_parser *parser,
struct jal_expr expr)
{
	tree idx;
	tree exprlist;

	location_t loc = jal_parser_peek_token (parser)->location;

	jal_parser_trace0(  "jal_parser_postfix_expression_after_primary 1" );

	while (true)
	{
		switch (jal_parser_peek_token (parser)->type)
		{
		case CPP_OPEN_SQUARE:
			/* Array reference.  */
			jal_parser_trace0(  "jal_parser_postfix_expression_after_primary 2" );
			jal_parser_consume_token (parser);
			idx = jal_parser_expression (parser).value;
			jal_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
			expr.value = build_array_ref (expr.value, idx,loc);
			expr.original_code = ERROR_MARK;
			break;
		case CPP_OPEN_PAREN:
			/* Function call.  */
			jal_parser_trace0(  "jal_parser_postfix_expression_after_primary 3" );

			jal_parser_consume_token (parser);
			if (jal_parser_next_token_is (parser, CPP_CLOSE_PAREN))
				exprlist = NULL_TREE;
			else
			{
				jal_parser_trace0(  "CALL jal_parser_expr_list FROM C" );

				exprlist = jal_parser_expr_list (parser, true);
			}
			jal_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "7 expected %<)%>");
			expr.value = build_function_call (expr.value, exprlist);
			expr.original_code = ERROR_MARK;
			break;
		//case CPP_DOT:
		//	/* Structure element reference.  */
		//	jal_parser_consume_token (parser);
		//	expr = default_function_array_conversion (expr);
		//	if (jal_parser_next_token_is (parser, CPP_NAME))
		//		ident = jal_parser_peek_token (parser)->value;
		//	else
		//	{
		//		jal_parser_error (parser, "expected identifier");
		//		expr.value = error_mark_node;
		//		expr.original_code = ERROR_MARK;
		//		return expr;
		//	}
		//	jal_parser_consume_token (parser);
		//	expr.value = build_component_ref (expr.value, ident);
		//	expr.original_code = ERROR_MARK;
		//	break;
		//case CPP_DEREF:
		//	/* Structure element reference.  */
		//	jal_parser_consume_token (parser);
		//	expr = default_function_array_conversion (expr);
		//	if (jal_parser_next_token_is (parser, CPP_NAME))
		//		ident = jal_parser_peek_token (parser)->value;
		//	else
		//	{
		//		jal_parser_error (parser, "expected identifier");
		//		expr.value = error_mark_node;
		//		expr.original_code = ERROR_MARK;
		//		return expr;
		//	}
		//	jal_parser_consume_token (parser);
		//	expr.value = build_component_ref (build_indirect_ref (loc, expr.value,"->"), ident);
		//	expr.original_code = ERROR_MARK;
		//	break;
		default:
			return expr;
		}
	}
}


/* Parse an expression

expression:
assignment-expression
expression , assignment-expression
*/

static struct jal_expr jal_parser_expression (jal_parser *parser)
{
	struct jal_expr expr;

	jal_parser_trace0(  "jal_parser_expression ENTRY" );

	jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM V" );

	expr = jal_parser_expr_no_commas (parser, NULL);

	while (jal_parser_next_token_is (parser, CPP_COMMA))
	{
		struct jal_expr next;

		jal_parser_trace0(  "jal_parser_expression WHILE COMMA" );

		jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM W" );

		next = jal_parser_expr_no_commas (parser, NULL);
		next = default_function_array_conversion (next);
		expr.value = build_compound_expr (expr.value, next.value);
		expr.original_code = COMPOUND_EXPR;
	}
	jal_parser_trace0(  "jal_parser_expression EXIT" );

	return expr;
}

/* Parse an expression and convert functions or arrays to
pointers.  */

static struct jal_expr
jal_parser_expression_conv (jal_parser *parser)
{
	struct jal_expr expr;

	jal_parser_trace0(  "jal_parser_expression_conv ENTRY" );
	expr = jal_parser_expression (parser);
	expr = default_function_array_conversion (expr);
	jal_parser_trace0(  "jal_parser_expression_conv EXIT" );
	return expr;
}

/* Parse a non-empty list of expressions.  If CONVERT_P, convert
functions and arrays to pointers.

nonempty-expr-list:
assignment-expression
nonempty-expr-list , assignment-expression
*/

static tree
jal_parser_expr_list (jal_parser *parser, bool convert_p)
{
	struct jal_expr expr;
	tree ret, cur;
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM X" );

	expr = jal_parser_expr_no_commas (parser, NULL);
	if (convert_p)
		expr = default_function_array_conversion (expr);
	ret = cur = build_tree_list (NULL_TREE, expr.value);
	while (jal_parser_next_token_is (parser, CPP_COMMA))
	{
		jal_parser_consume_token (parser);
				jal_parser_trace0(  "CALL jal_parser_expr_no_commas FROM Y" );

		expr = jal_parser_expr_no_commas (parser, NULL);
		if (convert_p)
			expr = default_function_array_conversion (expr);
		cur = TREE_CHAIN (cur) = build_tree_list (NULL_TREE, expr.value);
	}
	return ret;
}

/* Handle pragmas.  Some OpenMP pragmas are associated with, and therefore
should be considered, statements.  ALLOW_STMT is true if we're within
the context of a function and such pragmas are to be allowed.  Returns
true if we actually parsed such a pragma.  */

static bool
jal_parser_pragma (jal_parser *parser, enum pragma_context context)
{
	unsigned int id;

	id = jal_parser_peek_token (parser)->pragma_kind;
	gcc_assert (id != PRAGMA_NONE);

	switch (id)
	{

	case PRAGMA_GCC_PCH_PREPROCESS:
		jal_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
		jal_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
		return false;

	default:
		if (id < PRAGMA_FIRST_EXTERNAL)
		{
			if (context == pragma_external)
			{
				jal_parser_error (parser, "expected declaration specifiers");
				jal_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
				return false;
			}
			return true;
		}
		break;
	}

	jal_parser_consume_pragma (parser);
	c_invoke_pragma_handler (id);

	/* Skip to EOL, but suppress any error message.  Those will have been 
	generated by the handler routine through calling error, as opposed
	to calling jal_parser_error.  */
	parser->error = true;
	jal_parser_skip_to_pragma_eol (parser);

	return false;
}

/* The interface the pragma parsers have to the lexer.  */

enum cpp_ttype
pragma_lex (tree *value)
{
	jal_token *tok = jal_parser_peek_token (the_parser);
	enum cpp_ttype ret = tok->type;

	*value = tok->value;
	if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
		ret = CPP_EOF;
	else
	{
		if (ret == CPP_KEYWORD)
			ret = CPP_NAME;
		jal_parser_consume_token (the_parser);
	}

	return ret;
}

static void
jal_parser_pragma_pch_preprocess (jal_parser *parser)
{
	tree name = NULL;

	jal_parser_consume_pragma (parser);
	if (jal_parser_next_token_is (parser, CPP_STRING))
	{
		name = jal_parser_peek_token (parser)->value;
		jal_parser_consume_token (parser);
	}
	else
		jal_parser_error (parser, "expected string literal");
	jal_parser_skip_to_pragma_eol (parser);

	//if (name)
	//	c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
}

/* Parse a single source file.  */

void
jal_parse_file (const char* fname)
{
	jal_parser tparser;

	jal_lexer_init();
	jal_pp_set_filename( fname );

	// AF TEMP, FIX LATER
	jal_parse_init();


	// AF TEMP
	//jal_lex_token_test();

	/* Use local storage to begin.  If the first token is a pragma, parse it.
	If it is #pragma GCC pch_preprocess, then this will load a PCH file
	which will cause garbage collection.  */

	memset (&tparser, 0, sizeof tparser);
	the_parser = &tparser;

	if (jal_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
		jal_parser_pragma_pch_preprocess (&tparser);

	the_parser = GGC_NEW (jal_parser);
	*the_parser = tparser;

	jal_parser_translation_unit (the_parser);
	the_parser = NULL;
}
#include "gt-jal-jal-parser.h"
